Related
Tried to googled it but with no luck.
How can I find the second maximum number in an array with the smallest complexity?
code OR idea will be much help.
I can loop through an array and look for the maximum number
after that, I have the maximum number and then loop the array again to find the second the same way.
But for sure it is not efficient.
You could sort the array and choose the item at the second index, but the following O(n) loop will be much faster.
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
int largest = int.MinValue;
int second = int.MinValue;
foreach (int i in myArray)
{
if (i > largest)
{
second = largest;
largest = i;
}
else if (i > second)
second = i;
}
System.Console.WriteLine(second);
OR
Try this (using LINQ):
int secondHighest = (from number in test
orderby number descending
select number).Distinct().Skip(1).First()
How to get the second highest number in an array in Visual C#?
Answer in C# :
static void Main(string[] args)
{
//let us define array and vars
var arr = new int[]{ 100, -3, 95,100,95, 177,-5,-4,177,101 };
int biggest =0, secondBiggest=0;
for (int i = 0; i < arr.Length; ++i)
{
int arrItem = arr[i];
if(arrItem > biggest)
{
secondBiggest = biggest; //always store the prev value of biggest
//to second biggest...
biggest = arrItem;
}
else if (arrItem > secondBiggest && arrItem < biggest) //if in our
//iteration we will find a number that is bigger than secondBiggest and smaller than biggest
secondBiggest = arrItem;
}
Console.WriteLine($"Biggest Number:{biggest}, SecondBiggestNumber:
{secondBiggest}");
Console.ReadLine(); //make program wait
}
Output : Biggest Number:177, SecondBiggestNumber:101
public static int F(int[] array)
{
array = array.OrderByDescending(c => c).Distinct().ToArray();
switch (array.Count())
{
case 0:
return -1;
case 1:
return array[0];
}
return array[1];
}
static void Main(string[] args)
{
int[] myArray = new int[] { 0, 11, 2, 15, 16, 8, 16 ,8,15};
int Smallest = myArray.Min();
int Largest = myArray.Max();
foreach (int i in myArray)
{
if(i>Smallest && i<Largest)
{
Smallest=i;
}
}
System.Console.WriteLine(Smallest);
Console.ReadLine();
}
This will work even if you have reputation of items in an array
int[] arr = {-10, -3, -3, -6};
int h = int.MinValue, m = int.MinValue;
foreach (var t in arr)
{
if (t == h || t == m)
continue;
if (t > h)
{
m = h;
h = t;
}
else if(t > m )
{
m = t;
}
}
Console.WriteLine("High: {0} 2nd High: {1}", h, m);
//or,
m = arr.OrderByDescending(i => i).Distinct().Skip(1).First();
Console.WriteLine("High: {0} 2nd High: {1}", h, m);
/* we can use recursion */
var counter = 0;
findSecondMax = (arr)=> {
let max = Math.max(...arr);
counter++;
return counter == 1 ? findSecondMax(arr.slice(0,arr.indexOf(max)).concat(arr.slice(arr.indexOf(max)+1))) : max;
}
console.log(findSecondMax([1,5,2,3,0]))
static void Main(string[] args){
int[] arr = new int[5];
int i, j,k;
Console.WriteLine("Enter Array");
for (i = 0; i < 5; i++) {
Console.Write("element - {0} : ", i);
arr[i] = Convert.ToInt32(Console.ReadLine());
}
Console.Write("\nElements in array are: ");
j=arr[0];
k=j;
for (i = 1; i < 5; i++) {
if (j < arr[i])
{
if(j>k)
{
k=j;
}
j=arr[i];
}
}
Console.WriteLine("First Greatest element: "+ j);
Console.WriteLine("Second Greatest element: "+ k);
Console.Write("\n");
}
int max = 0;
int secondmax = 0;
int[] arr = { 2, 11, 15, 1, 7, 99, 6, 85, 4 };
for (int r = 0; r < arr.Length; r++)
{
if (max < arr[r])
{
max = arr[r];
}
}
for (int r = 0; r < arr.Length; r++)
{
if (secondmax < arr[r] && arr[r] < max)
{
secondmax = arr[r];
}
}
Console.WriteLine(max);
Console.WriteLine(secondmax);
Console.Read();
Python 36>=
def sec_max(array: list) -> int:
_max_: int = max(array)
second: int = 0
for element in array:
if second < element < _max_:
second = element
else:
continue
return second
Using below code we can find out second highest number, even array contains multiple max numbers
// int[] myArray = { 25, 25, 5, 20, 50, 23, 10 };
public static int GetSecondHighestNumberForUniqueNumbers(int[] numbers)
{
int highestNumber = 0, Seconhight = 0;
List<int> numberList = new List<int>();
for (int i = 0; i < numbers.Length; i++)
{
//For loop should move forward only for unique items
if (numberList.Contains(numbers[i]))
continue;
else
numberList.Add(numbers[i]);
//find higest number
if (highestNumber < numbers[i])
{
Seconhight = highestNumber;
highestNumber = numbers[i];
} //find second highest number
else if (Seconhight < numbers[i])
{
Seconhight = numbers[i];
}
}
It's not like that your structure is a tree...It's just a simple array, right?
The best solution is to sort the array. And depending on descending or ascending, display the second or the 2nd last element respectively.
The other alternative is to use some inbuilt methods, to get the initial max. Pop that element, and then search for the max again. Don't know C#, so can't give the direct code.
You'd want to sort the numbers, then just take the second largest. Here's a snippet without any consideration of efficiency:
var numbers = new int[] { 3, 5, 1, 5, 4 };
var result=numbers.OrderByDescending(x=>x).Distinct().Skip(1).First();
This isn't too bad:
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
var secondMax =
myArray.Skip(2).Aggregate(
myArray.Take(2).OrderByDescending(x => x).AsEnumerable(),
(a, x) => a.Concat(new [] { x }).OrderByDescending(y => y).Take(2))
.Skip(1)
.First();
It's fairly low on complexity as it only every sorts a maximum of three elements
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int size;
Console.WriteLine("Enter the size of array");
size = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the element of array");
int[] arr = new int[size];
for (int i = 0; i < size; i++)
{
arr[i] = Convert.ToInt32(Console.ReadLine());
}
int length = arr.Length;
Program program = new Program();
program.SeconadLargestValue(arr, length);
}
private void SeconadLargestValue(int[] arr, int length)
{
int maxValue = 0;
int secondMaxValue = 0;
for (int i = 0; i < length; i++)
{
if (arr[i] > maxValue)
{
secondMaxValue = maxValue;
maxValue = arr[i];
}
else if(arr[i] > secondMaxValue)
{
secondMaxValue = arr[i];
}
}
Console.WriteLine("First Largest number :"+maxValue);
Console.WriteLine("Second Largest number :"+secondMaxValue);
Console.ReadLine();
}
}
}
My solution below.
class Program
{
static void Main(string[] args)
{
Program pg = new Program();
Console.WriteLine("*****************************Program to Find 2nd Highest and 2nd lowest from set of values.**************************");
Console.WriteLine("Please enter the comma seperated numbers : ");
string[] val = Console.ReadLine().Split(',');
int[] inval = Array.ConvertAll(val, int.Parse); // Converts Array from one type to other in single line or Following line
// val.Select(int.Parse)
Array.Sort(inval);
Console.WriteLine("2nd Highest is : {0} \n 2nd Lowest is : {1}", pg.Return2ndHighest(inval), pg.Return2ndLowest(inval));
Console.ReadLine();
}
//Method to get the 2nd lowest and 2nd highest from list of integers ex 1000,20,-10,40,100,200,400
public int Return2ndHighest(int[] values)
{
if (values.Length >= 2)
return values[values.Length - 2];
else
return values[0];
}
public int Return2ndLowest(int[] values)
{
if (values.Length > 2)
return values[1];
else
return values[0];
}
}
I am giving solution that's in JavaScript, it takes o(n/2) complexity to find the highest and second highest number.
here is the working Fiddler Link
var num=[1020215,2000,35,2,54546,456,2,2345,24,545,132,5469,25653,0,2315648978523];
var j=num.length-1;
var firstHighest=0,seoncdHighest=0;
num[0] >num[num.length-1]?(firstHighest=num[0],seoncdHighest=num[num.length-1]):(firstHighest=num[num.length-1], seoncdHighest=num[0]);
j--;
for(var i=1;i<=num.length/2;i++,j--)
{
if(num[i] < num[j] )
{
if(firstHighest < num[j]){
seoncdHighest=firstHighest;
firstHighest= num[j];
}
else if(seoncdHighest < num[j] ) {
seoncdHighest= num[j];
}
}
else {
if(firstHighest < num[i])
{
seoncdHighest=firstHighest;
firstHighest= num[i];
}
else if(seoncdHighest < num[i] ) {
seoncdHighest= num[i];
}
}
}
Sort the array and take the second to last value?
var result = (from elements in inputElements
orderby elements descending
select elements).Distinct().Skip(1).Take(1);
return result.FirstOrDefault();
namespace FindSecondLargestNumber
{
class Program
{
static void Main(string[] args)
{
int max=0;
int smax=0;
int i;
int[] a = new int[20];
Console.WriteLine("enter the size of the array");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("elements");
for (i = 0; i < n; i++)
{
a[i] = int.Parse(Console.ReadLine());
}
for (i = 0; i < n; i++)
{
if ( a[i]>max)
{
smax = max;
max= a[i];
}
else if(a[i]>smax)
{
smax=a[i];
}
}
Console.WriteLine("max:" + max);
Console.WriteLine("second max:"+smax);
Console.ReadLine();
}
}
}
I need to find the value and position of the lowest entry in the table. Problem is, I don't know how to specify it. I can't put any numeric in the int value for minimum because the user can always specify a higher value. It works for the highest value but it doesn't for the smallest.
Console.WriteLine("Podaj wymiar tablicy.");
int dlugosc = Convert.ToInt32(Console.ReadLine());
int[] tablica = new int[dlugosc];
int max = 0;
int min = tablica[0];
for (int i = 0; i < tablica.Length; i++)
{
Console.WriteLine("Podaj wartosc {0} elementu.", i + 1);
tablica[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < tablica.Length; i++)
{
while (tablica[i] > max)
{
max = tablica[i];
}
}
for (int x = 0; x < tablica.Length; x++)
{
while (tablica[x] < min)
{
min = tablica[x];
}
}
int najmniejsze_miejsce = Array.IndexOf(tablica, min);
int najwieksze_miejsce = Array.IndexOf(tablica, max);
Console.WriteLine("Najwyzsza wartosc tablicy to {0}.", max);
Console.WriteLine("Najwieksza wartosc wystepuje na miejscu {0}.", najwieksze_miejsce);
Console.WriteLine("Najniższa wartość tablicy to {0}.", min);
Console.WriteLine("Najnizsza wartosc wystepuje na miejscu {0}", najmniejsze_miejsce);
Console.ReadKey();
you can just use:
Console.WriteLine(tablica.Min());
since your using an integer array
The current code is below:
int min = tablica[0];
for (int i = 0; i < tablica.Length; i++)
{
Console.WriteLine("Podaj wartosc {0} elementu.", i + 1);
tablica[i] = Convert.ToInt32(Console.ReadLine());
}
The min value being declared before the array is initialized means it will simply be zero. No value from your array can ever be less unless it's a negative number.
To fix, the min should be declared after the array is initialized:
for (int i = 0; i < tablica.Length; i++)
{
Console.WriteLine("Podaj wartosc {0} elementu.", i + 1);
tablica[i] = Convert.ToInt32(Console.ReadLine());
}
int min = tablica[0];`
You can find the first occurence of the min value in your table
int minIndex = Array.IndexOf(tablica, tablica.Min());
or simple:
Console.WriteLine(Convert.ToString(Array.IndexOf(tablica, tablica.Min())));
When you do need to do a scan you typically set the min value to Int.MaxValue and the max value to Int.MinValue before the loop and then you are guaranteed to set it on the first element and any element that improves either value.
You can then do it all in one loop (and you don't need to use while when you mean if). You can also track the index as you go:
int max = Int.MinValue;
int min = Int.MaxValue;
int maxindex = -1;
int minindex = -1;
for (int i = 0; i < tablica.Length; i++)
{
if (tablica[i] > max) { max = tablica[i]; maxindex = i; }
if (tablica[i] < min) { min = tablica[i]; minindex = i; }
}
Hi I am trying to make a program where the user can enter up to 25 numbers and then it tells the user the average, smallest and largest number and the mode of the numbers entered but I am not sure on how to do this.
Any Guidance would be appreciated
here is what I have so far
static void Main(string[] args)
{
Console.WriteLine("enter the amount of numbers you would like to use of: ");
int arraylength = Int32.Parse(Console.ReadLine());
int[] AverageArray = new int[25];
//filling the array with user input
for (int i = 0; i < AverageArray.Length; i++)
{
Console.Write("enter the numbers you wish to find the average for: ");
AverageArray[i] = Int32.Parse(Console.ReadLine());
}
//printing out the array
Console.WriteLine("here is the average: ");
for (int i = 0; i < AverageArray.Length; i++)
{
Console.WriteLine(AverageArray[i]);
}
Console.WriteLine(FindAverage(AverageArray));
}
public static double FindAverage(int[] averageNumbers)
{
int arraySum = 0;
for (int i = 0; i < averageNumbers.Length; i++)
arraySum += averageNumbers[i];
return arraySum / averageNumbers.Length;
}
public static double LargestNumber(int[] Nums, int Count)
{
}
public static double SmallestNumber(int[] Nums, int Count)
{
}
public static double Mode(int[] Nums, int Count)
{
}
}
var smallest = AverageArray.Min();
var largest = AverageArray.Max();
var mode = AverageArray.GroupBy(v => v)
.OrderByDescending(g => g.Count())
.First()
.Key;
If you don't know how to use linq
/*Assign Initial Value*/
int highestNum = numberArray[0];
int lowestNum = numberArray[0];
int sum = 0;
foreach (int item in numberArray)
{
/*Get The Highest Number*/
if (item > highestNum)
{
highestNum = item;
}
/*Get The Lowest Number*/
if (item < highestNum)
{
lowestNum = item;
}
//get the sum
sum = item + sum;
}
//display the Highest Num
Console.WriteLine(highestNum);
//display the Lowest Num
Console.WriteLine(lowestNum);
//Display The Average up to 2 decimal Places
Console.WriteLine((sum/numberArray.Length).ToString("0.00"));
public static double LargestNumber(int[] Nums, int Count)
{
double max = Nums[0];
for (int i = 1; i < Count; i++)
if (Nums[i] > max) max = Nums[i];
return min;
}
public static double SmallestNumber(int[] Nums, int Count)
{
double min = Nums[0];
for (int i = 1; i < Count; i++)
if (Nums[i] < min) min = Nums[i];
return min;
}
public static double Mode(int[] Nums, int Count)
{
double mode = Nums[0];
int maxCount = 1;
for (int i = 0; i < Count; i++)
{
int val = Nums[i];
int count = 1;
for (int j = i+1; j < Count; j++)
{
if (Nums[j] == val)
count++;
}
if (count > maxCount)
{
mode = val;
maxCount = count;
}
}
return mode;
}
Tried to googled it but with no luck.
How can I find the second maximum number in an array with the smallest complexity?
code OR idea will be much help.
I can loop through an array and look for the maximum number
after that, I have the maximum number and then loop the array again to find the second the same way.
But for sure it is not efficient.
You could sort the array and choose the item at the second index, but the following O(n) loop will be much faster.
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
int largest = int.MinValue;
int second = int.MinValue;
foreach (int i in myArray)
{
if (i > largest)
{
second = largest;
largest = i;
}
else if (i > second)
second = i;
}
System.Console.WriteLine(second);
OR
Try this (using LINQ):
int secondHighest = (from number in test
orderby number descending
select number).Distinct().Skip(1).First()
How to get the second highest number in an array in Visual C#?
Answer in C# :
static void Main(string[] args)
{
//let us define array and vars
var arr = new int[]{ 100, -3, 95,100,95, 177,-5,-4,177,101 };
int biggest =0, secondBiggest=0;
for (int i = 0; i < arr.Length; ++i)
{
int arrItem = arr[i];
if(arrItem > biggest)
{
secondBiggest = biggest; //always store the prev value of biggest
//to second biggest...
biggest = arrItem;
}
else if (arrItem > secondBiggest && arrItem < biggest) //if in our
//iteration we will find a number that is bigger than secondBiggest and smaller than biggest
secondBiggest = arrItem;
}
Console.WriteLine($"Biggest Number:{biggest}, SecondBiggestNumber:
{secondBiggest}");
Console.ReadLine(); //make program wait
}
Output : Biggest Number:177, SecondBiggestNumber:101
public static int F(int[] array)
{
array = array.OrderByDescending(c => c).Distinct().ToArray();
switch (array.Count())
{
case 0:
return -1;
case 1:
return array[0];
}
return array[1];
}
static void Main(string[] args)
{
int[] myArray = new int[] { 0, 11, 2, 15, 16, 8, 16 ,8,15};
int Smallest = myArray.Min();
int Largest = myArray.Max();
foreach (int i in myArray)
{
if(i>Smallest && i<Largest)
{
Smallest=i;
}
}
System.Console.WriteLine(Smallest);
Console.ReadLine();
}
This will work even if you have reputation of items in an array
int[] arr = {-10, -3, -3, -6};
int h = int.MinValue, m = int.MinValue;
foreach (var t in arr)
{
if (t == h || t == m)
continue;
if (t > h)
{
m = h;
h = t;
}
else if(t > m )
{
m = t;
}
}
Console.WriteLine("High: {0} 2nd High: {1}", h, m);
//or,
m = arr.OrderByDescending(i => i).Distinct().Skip(1).First();
Console.WriteLine("High: {0} 2nd High: {1}", h, m);
/* we can use recursion */
var counter = 0;
findSecondMax = (arr)=> {
let max = Math.max(...arr);
counter++;
return counter == 1 ? findSecondMax(arr.slice(0,arr.indexOf(max)).concat(arr.slice(arr.indexOf(max)+1))) : max;
}
console.log(findSecondMax([1,5,2,3,0]))
static void Main(string[] args){
int[] arr = new int[5];
int i, j,k;
Console.WriteLine("Enter Array");
for (i = 0; i < 5; i++) {
Console.Write("element - {0} : ", i);
arr[i] = Convert.ToInt32(Console.ReadLine());
}
Console.Write("\nElements in array are: ");
j=arr[0];
k=j;
for (i = 1; i < 5; i++) {
if (j < arr[i])
{
if(j>k)
{
k=j;
}
j=arr[i];
}
}
Console.WriteLine("First Greatest element: "+ j);
Console.WriteLine("Second Greatest element: "+ k);
Console.Write("\n");
}
int max = 0;
int secondmax = 0;
int[] arr = { 2, 11, 15, 1, 7, 99, 6, 85, 4 };
for (int r = 0; r < arr.Length; r++)
{
if (max < arr[r])
{
max = arr[r];
}
}
for (int r = 0; r < arr.Length; r++)
{
if (secondmax < arr[r] && arr[r] < max)
{
secondmax = arr[r];
}
}
Console.WriteLine(max);
Console.WriteLine(secondmax);
Console.Read();
Python 36>=
def sec_max(array: list) -> int:
_max_: int = max(array)
second: int = 0
for element in array:
if second < element < _max_:
second = element
else:
continue
return second
Using below code we can find out second highest number, even array contains multiple max numbers
// int[] myArray = { 25, 25, 5, 20, 50, 23, 10 };
public static int GetSecondHighestNumberForUniqueNumbers(int[] numbers)
{
int highestNumber = 0, Seconhight = 0;
List<int> numberList = new List<int>();
for (int i = 0; i < numbers.Length; i++)
{
//For loop should move forward only for unique items
if (numberList.Contains(numbers[i]))
continue;
else
numberList.Add(numbers[i]);
//find higest number
if (highestNumber < numbers[i])
{
Seconhight = highestNumber;
highestNumber = numbers[i];
} //find second highest number
else if (Seconhight < numbers[i])
{
Seconhight = numbers[i];
}
}
It's not like that your structure is a tree...It's just a simple array, right?
The best solution is to sort the array. And depending on descending or ascending, display the second or the 2nd last element respectively.
The other alternative is to use some inbuilt methods, to get the initial max. Pop that element, and then search for the max again. Don't know C#, so can't give the direct code.
You'd want to sort the numbers, then just take the second largest. Here's a snippet without any consideration of efficiency:
var numbers = new int[] { 3, 5, 1, 5, 4 };
var result=numbers.OrderByDescending(x=>x).Distinct().Skip(1).First();
This isn't too bad:
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
var secondMax =
myArray.Skip(2).Aggregate(
myArray.Take(2).OrderByDescending(x => x).AsEnumerable(),
(a, x) => a.Concat(new [] { x }).OrderByDescending(y => y).Take(2))
.Skip(1)
.First();
It's fairly low on complexity as it only every sorts a maximum of three elements
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int size;
Console.WriteLine("Enter the size of array");
size = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the element of array");
int[] arr = new int[size];
for (int i = 0; i < size; i++)
{
arr[i] = Convert.ToInt32(Console.ReadLine());
}
int length = arr.Length;
Program program = new Program();
program.SeconadLargestValue(arr, length);
}
private void SeconadLargestValue(int[] arr, int length)
{
int maxValue = 0;
int secondMaxValue = 0;
for (int i = 0; i < length; i++)
{
if (arr[i] > maxValue)
{
secondMaxValue = maxValue;
maxValue = arr[i];
}
else if(arr[i] > secondMaxValue)
{
secondMaxValue = arr[i];
}
}
Console.WriteLine("First Largest number :"+maxValue);
Console.WriteLine("Second Largest number :"+secondMaxValue);
Console.ReadLine();
}
}
}
My solution below.
class Program
{
static void Main(string[] args)
{
Program pg = new Program();
Console.WriteLine("*****************************Program to Find 2nd Highest and 2nd lowest from set of values.**************************");
Console.WriteLine("Please enter the comma seperated numbers : ");
string[] val = Console.ReadLine().Split(',');
int[] inval = Array.ConvertAll(val, int.Parse); // Converts Array from one type to other in single line or Following line
// val.Select(int.Parse)
Array.Sort(inval);
Console.WriteLine("2nd Highest is : {0} \n 2nd Lowest is : {1}", pg.Return2ndHighest(inval), pg.Return2ndLowest(inval));
Console.ReadLine();
}
//Method to get the 2nd lowest and 2nd highest from list of integers ex 1000,20,-10,40,100,200,400
public int Return2ndHighest(int[] values)
{
if (values.Length >= 2)
return values[values.Length - 2];
else
return values[0];
}
public int Return2ndLowest(int[] values)
{
if (values.Length > 2)
return values[1];
else
return values[0];
}
}
I am giving solution that's in JavaScript, it takes o(n/2) complexity to find the highest and second highest number.
here is the working Fiddler Link
var num=[1020215,2000,35,2,54546,456,2,2345,24,545,132,5469,25653,0,2315648978523];
var j=num.length-1;
var firstHighest=0,seoncdHighest=0;
num[0] >num[num.length-1]?(firstHighest=num[0],seoncdHighest=num[num.length-1]):(firstHighest=num[num.length-1], seoncdHighest=num[0]);
j--;
for(var i=1;i<=num.length/2;i++,j--)
{
if(num[i] < num[j] )
{
if(firstHighest < num[j]){
seoncdHighest=firstHighest;
firstHighest= num[j];
}
else if(seoncdHighest < num[j] ) {
seoncdHighest= num[j];
}
}
else {
if(firstHighest < num[i])
{
seoncdHighest=firstHighest;
firstHighest= num[i];
}
else if(seoncdHighest < num[i] ) {
seoncdHighest= num[i];
}
}
}
Sort the array and take the second to last value?
var result = (from elements in inputElements
orderby elements descending
select elements).Distinct().Skip(1).Take(1);
return result.FirstOrDefault();
namespace FindSecondLargestNumber
{
class Program
{
static void Main(string[] args)
{
int max=0;
int smax=0;
int i;
int[] a = new int[20];
Console.WriteLine("enter the size of the array");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("elements");
for (i = 0; i < n; i++)
{
a[i] = int.Parse(Console.ReadLine());
}
for (i = 0; i < n; i++)
{
if ( a[i]>max)
{
smax = max;
max= a[i];
}
else if(a[i]>smax)
{
smax=a[i];
}
}
Console.WriteLine("max:" + max);
Console.WriteLine("second max:"+smax);
Console.ReadLine();
}
}
}
Is the following 0-1 Knapsack problem solvable:
'float' positive values and
'float' weights (can be positive or negative)
'float' capacity of the knapsack > 0
I have on average < 10 items, so I'm thinking of using a brute force implementation. However, I was wondering if there is a better way of doing it.
This is a relatively simple binary program.
I'd suggest brute force with pruning. If at any time you exceed the allowable weight, you don't need to try combinations of additional items, you can discard the whole tree.
Oh wait, you have negative weights? Include all negative weights always, then proceed as above for the positive weights. Or do the negative weight items also have negative value?
Include all negative weight items with positive value. Exclude all items with positive weight and negative value.
For negative weight items with negative value, subtract their weight (increasing the knapsack capavity) and use a pseudo-item which represents not taking that item. The pseudo-item will have positive weight and value. Proceed by brute force with pruning.
class Knapsack
{
double bestValue;
bool[] bestItems;
double[] itemValues;
double[] itemWeights;
double weightLimit;
void SolveRecursive( bool[] chosen, int depth, double currentWeight, double currentValue, double remainingValue )
{
if (currentWeight > weightLimit) return;
if (currentValue + remainingValue < bestValue) return;
if (depth == chosen.Length) {
bestValue = currentValue;
System.Array.Copy(chosen, bestItems, chosen.Length);
return;
}
remainingValue -= itemValues[depth];
chosen[depth] = false;
SolveRecursive(chosen, depth+1, currentWeight, currentValue, remainingValue);
chosen[depth] = true;
currentWeight += itemWeights[depth];
currentValue += itemValues[depth];
SolveRecursive(chosen, depth+1, currentWeight, currentValue, remainingValue);
}
public bool[] Solve()
{
var chosen = new bool[itemWeights.Length];
bestItems = new bool[itemWeights.Length];
bestValue = 0.0;
double totalValue = 0.0;
foreach (var v in itemValues) totalValue += v;
SolveRecursive(chosen, 0, 0.0, 0.0, totalValue);
return bestItems;
}
}
Yeah, brute force it. This is an NP-Complete problem, but that shouldn't matter because you will have less than 10 items. Brute forcing won't be problematic.
var size = 10;
var capacity = 0;
var permutations = 1024;
var repeat = 10000;
// Generate items
float[] items = new float[size];
float[] weights = new float[size];
Random rand = new Random();
for (int i = 0; i < size; i++)
{
items[i] = (float)rand.NextDouble();
weights[i] = (float)rand.NextDouble();
if (rand.Next(2) == 1)
{
weights[i] *= -1;
}
}
// solution
int bestPosition= -1;
Stopwatch sw = new Stopwatch();
sw.Start();
// for perf testing
//for (int r = 0; r < repeat; r++)
{
var bestValue = 0d;
// solve
for (int i = 0; i < permutations; i++)
{
var total = 0d;
var weight = 0d;
for (int j = 0; j < size; j++)
{
if (((i >> j) & 1) == 1)
{
total += items[j];
weight += weights[j];
}
}
if (weight <= capacity && total > bestValue)
{
bestPosition = i;
bestValue = total;
}
}
}
sw.Stop();
sw.Elapsed.ToString();
If you can only have positive values then every item with a negative weight must go in.
Then I guess you could calculate Value/Weight Ratio, and brute force the remaining combinations based on that order, once you get one that fits you can skip the rest.
The problem may be that the grading and sorting is actually more expensive than just doing all the calculations.
There will obviously be a different breakeven point based on the size and distribution of the set.
public class KnapSackSolver {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]); // number of items
int W = Integer.parseInt(args[1]); // maximum weight of knapsack
int[] profit = new int[N + 1];
int[] weight = new int[N + 1];
// generate random instance, items 1..N
for (int n = 1; n <= N; n++) {
profit[n] = (int) (Math.random() * 1000);
weight[n] = (int) (Math.random() * W);
}
// opt[n][w] = max profit of packing items 1..n with weight limit w
// sol[n][w] = does opt solution to pack items 1..n with weight limit w
// include item n?
int[][] opt = new int[N + 1][W + 1];
boolean[][] sol = new boolean[N + 1][W + 1];
for (int n = 1; n <= N; n++) {
for (int w = 1; w <= W; w++) {
// don't take item n
int option1 = opt[n - 1][w];
// take item n
int option2 = Integer.MIN_VALUE;
if (weight[n] <= w)
option2 = profit[n] + opt[n - 1][w - weight[n]];
// select better of two options
opt[n][w] = Math.max(option1, option2);
sol[n][w] = (option2 > option1);
}
}
// determine which items to take
boolean[] take = new boolean[N + 1];
for (int n = N, w = W; n > 0; n--) {
if (sol[n][w]) {
take[n] = true;
w = w - weight[n];
} else {
take[n] = false;
}
}
// print results
System.out.println("item" + "\t" + "profit" + "\t" + "weight" + "\t"
+ "take");
for (int n = 1; n <= N; n++) {
System.out.println(n + "\t" + profit[n] + "\t" + weight[n] + "\t"
+ take[n]);
}
}
}
import java.util.*;
class Main{
static int max(inta,int b)
{
if(a>b)
return a;
else
return b;
}
public static void main(String args[])
{
int n,i,cap,j,t=2,w;
Scanner sc=new Scanner(System.in);
System.out.println("Enter the number of values ");
n=sc.nextInt();
int solution[]=new int[n];
System.out.println("Enter the capacity of the knapsack :- ");
cap=sc.nextInt();
int v[]=new int[n+1];
int wt[]=new int[n+1];
System.out.println("Enter the values ");
for(i=1;i<=n;i++)
{
v[i]=sc.nextInt();
}
System.out.println("Enter the weights ");
for(i=1;i<=n;i++)
{
wt[i]=sc.nextInt();
}
int knapsack[][]=new int[n+2][cap+1];
for(i=1;i<n+2;i++)
{
for(j=1;j<n+1;j++)
{
knapsack[i][j]=0;
}
}
/*for(i=1;i<n+2;i++)
{
for(j=wt[1]+1;j<cap+2;j++)
{
knapsack[i][j]=v[1];
}
}*/
int k;
for(i=1;i<n+1;i++)
{
for(j=1;j<cap+1;j++)
{
/*if(i==1||j==1)
{
knapsack[i][j]=0;
}*/
if(wt[i]>j)
{
knapsack[i][j]=knapsack[i-1][j];
}
else
{
knapsack[i][j]=max(knapsack[i-1][j],v[i]+knapsack[i-1][j-wt[i]]);
}
}
}
//for displaying the knapsack
for(i=0;i<n+1;i++)
{
for(j=0;j<cap+1;j++)
{
System.out.print(knapsack[i][j]+" ");
}
System.out.print("\n");
}
w=cap;k=n-1;
j=cap;
for(i=n;i>0;i--)
{
if(knapsack[i][j]!=knapsack[i-1][j])
{
j=w-wt[i];
w=j;
solution[k]=1;
System.out.println("k="+k);
k--;
}
else
{
solution[k]=0;
k--;
}
}
System.out.println("Solution for given knapsack is :- ");
for(i=0;i<n;i++)
{
System.out.print(solution[i]+", ");
}
System.out.print(" => "+knapsack[n][cap]);
}
}
This can be solved using Dynamic Programming. Below code can help you solve the 0/1 Knapsack problem using Dynamic Programming.
internal class knapsackProblem
{
private int[] weight;
private int[] profit;
private int capacity;
private int itemCount;
private int[,] data;
internal void GetMaxProfit()
{
ItemDetails();
data = new int[itemCount, capacity + 1];
for (int i = 1; i < itemCount; i++)
{
for (int j = 1; j < capacity + 1; j++)
{
int q = j - weight[i] >= 0 ? data[i - 1, j - weight[i]] + profit[i] : 0;
if (data[i - 1, j] > q)
{
data[i, j] = data[i - 1, j];
}
else
{
data[i, j] = q;
}
}
}
Console.WriteLine($"\nMax profit can be made : {data[itemCount-1, capacity]}");
IncludedItems();
}
private void ItemDetails()
{
Console.Write("\nEnter the count of items to be inserted : ");
itemCount = Convert.ToInt32(Console.ReadLine()) + 1;
Console.WriteLine();
weight = new int[itemCount];
profit = new int[itemCount];
for (int i = 1; i < itemCount; i++)
{
Console.Write($"Enter weight of item {i} : ");
weight[i] = Convert.ToInt32(Console.ReadLine());
Console.Write($"Enter the profit on the item {i} : ");
profit[i] = Convert.ToInt32(Console.ReadLine());
Console.WriteLine();
}
Console.Write("\nEnter the capacity of the knapsack : ");
capacity = Convert.ToInt32(Console.ReadLine());
}
private void IncludedItems()
{
int i = itemCount - 1;
int j = capacity;
while(i > 0)
{
if(data[i, j] == data[i - 1, j])
{
Console.WriteLine($"Item {i} : Not included");
i--;
}
else
{
Console.WriteLine($"Item {i} : Included");
j = j - weight[i];
i--;
}
}
}
}