c# Find the Longest Continuous Subarrays first and last elements Indexes - c#

In the inputs first row, there are two numbers the first one is the amount of rows N and the second one is a limit K. I have to find the first and last element's indexes of the longest continuous subarray which's elements are greater than K.
(There are lots of inputs with different numbers, but they have the same base.)
The example input is:
7 20
18
23
44
32
9
30
26
So the N is 7 and K is 20, in this case there are 2 continuous subarrays which would be correct: [23, 44, 32] and [30, 26], but I only need the longer ones indexes.
Therefore the output is:
1 3
I have split the first row, so i have the N and K, I have added the remaining rows in an array H[ ]. Now I just have to find the longest continuous subarray and get the first and last element's indexes.
static void Main(string[] args)
{
string[] fRow = Console.ReadLine().Split(' ');
int N = int.Parse(fRow[0]);
int K = int.Parse(fRow[1]);
int[] H = new int[N];
for (int i = 0; i < N; i++)
{
H[i] = int.Parse(Console.ReadLine());
}
}
And I'm stuck here, if someone could help me I would greatly appreciate their assistance.

Sounds like homework, but an interesting challenge none the less. Here's one way of doing it.
static void Main(string[] args)
{
string[] fRow = Console.ReadLine().Split(' ');
int N = int.Parse(fRow[0]);
int K = int.Parse(fRow[1]);
int[] H = new int[N];
for (int i = 0; i < N; i++)
{
H[i] = int.Parse(Console.ReadLine());
}
int greatesRangeStartIndex = -1;
int greatestRangeEndIndex = -1;
int greatestIndexSpan = 0;
for (int i = 0; i < N; i++)
{
// Find the first array item that meets the criteria.
if (H[i] > K)
{
var rangeStartIndex = i;
// Continue spinning through the array while we still meet the criteria.
do
{
i++;
} while (i < N && H[i] > K);
var rangeEndIndex = i - 1;
// Determine the width of our current range and check if its our largest one.
// If the range is the biggest so far, store that as the current largest range.
var indexSpan = rangeEndIndex - rangeStartIndex + 1;
if (indexSpan > greatestIndexSpan)
{
greatesRangeStartIndex = rangeStartIndex;
greatestRangeEndIndex = rangeEndIndex;
greatestIndexSpan = indexSpan;
}
}
}
// Report out the results.
// Not part of the requirements, but will remove false reporting of the criteria being in index position 1.
if (greatesRangeStartIndex == -1 && greatestRangeEndIndex == -1)
{
Console.WriteLine($"No values in the array were greater than {K}.");
}
else
{
Console.WriteLine($"{greatesRangeStartIndex} {greatestRangeEndIndex}");
}
}

You could do something like this (could be improved a lot with LINQ, but i suppose this is an introduction exercise of some sorts, so i'll stick to this):
static void Main(string[] args)
{
string[] fRow = Console.ReadLine().Split(' ');
int N = int.Parse(fRow[0]);
int K = int.Parse(fRow[1]);
int[] H = new int[N];
int firstIndex = 0;
int lastIndex = 0;
int subarraySize = 0;
int firstIndexTemp = 0;
int lastIndexTemp = 0;
int subarraySizeTemp = 0;
bool arrayContinues = false;
for (int i = 0; i < N; i++)
{
//Read the newest index
H[i] = int.Parse(Console.ReadLine());
/*If arrrayContinues is true, and the current value is higher than the threshold K,
this means this is the continuation of a subarray. For now, the current value is the last index value
*/
if (H[i] > K && arrayContinues)
{
subarraySizeTemp++;
lastIndexTemp = i;
}
/*If arrrayContinues is false, but the current value is higher than the threshold K,
this means this is the first index of a new subarray
*/
else if (H[i] > K)
{
subarraySizeTemp = 1;
firstIndexTemp = i;
arrayContinues = true;
}
/*If we reach this statement, the current value is smaller than K,
* so the array streak stopped (or was already stopped by a previous smaller value)
*/
else
{
arrayContinues = false;
}
/* We're only interested in the largest subarray,
* so let's override the previous largest array only when the current one is larger.
*/
if(subarraySizeTemp > subarraySize)
{
subarraySize = subarraySizeTemp;
firstIndex = firstIndexTemp;
lastIndex = lastIndexTemp;
}
}
/*Let's print our result!*/
Console.WriteLine($"{firstIndex} {lastIndex}");
}

Other answers work out but you can use something simpler like this;
private static void Main()
{
var input = Console.ReadLine().Split(' ');
var n = int.Parse(input[0]);
var k = int.Parse(input[1]);
var startingIndex = 0;
var endingIndex = 0;
var temporaryIndex = 0;
var items = new int[n];
for (var i = 0; i < n; i++)
{
var value = int.Parse(Console.ReadLine());
items[i] = value;
if (value < k)
{
temporaryIndex = i;
continue;
}
var currentSize = i - temporaryIndex;
var currentBiggestSize = endingIndex - startingIndex;
if (currentSize > currentBiggestSize)
{
startingIndex = temporaryIndex + 1;
endingIndex = i;
}
}
Console.WriteLine($"Biggest Subset's Start and Ending Indexes: {startingIndex} {endingIndex}");
Console.ReadLine();
}

Another Option:
static void Main(string[] args)
{
Example(new string[] { "7","20"},new string[] { "18", "23", "44", "32", "9", "30", "26"});
}
static void Example(string[] arr,string[] values)
{
int N = int.Parse(arr[0]);
int K = int.Parse(arr[1]);
int counter = 0;
int most_succesfull_index_yet = 0;
int most_succesfull_length_yet = 0;
for (int i = 1; i < N; i++)
{
if (int.Parse(values[i]) > K)
{
counter++;
}
else
{
if (counter > most_succesfull_length_yet)
{
most_succesfull_length_yet = counter;
most_succesfull_index_yet = i - counter;
}
counter = 0;
}
}
// For last index
if (counter > most_succesfull_length_yet)
{
most_succesfull_length_yet = counter;
most_succesfull_index_yet = N - counter;
}
var bestStart = most_succesfull_index_yet;
var bestEnd = most_succesfull_index_yet + most_succesfull_length_yet -1;
Console.WriteLine(bestStart + "," + bestEnd);
Console.ReadLine();
}

Another solution, keeping indexes of the longest match, and displaying the max length, indexes, and rows values at the end.
static void Main(string[] args)
{
var data = #"7 20
18
23
44
32
9
30
26";
var rows = data.Split("\r\n");
var frow = rows[0].Split(" ");
int N = int.Parse(frow[0]);
int K = int.Parse(frow[1]);
int max = 0, currentmax = 0;
int i = 1;
int[] indexes = null;
while(i < rows.Length)
{
if (int.Parse(rows[i]) > K)
{
currentmax++;
}
else
{
if (currentmax > max)
{
max = currentmax;
indexes = new int[max];
indexes[--currentmax] = i;
do
{
indexes[--currentmax] = indexes[currentmax + 1] - 1;
} while (currentmax > 0);
currentmax = 0;
}
}
i++;
}
if (indexes != null) {
Console.WriteLine($"{max} occured on indexes {string.Join(",", indexes)} with values {string.Join(",", indexes.Select(i => rows[i]).ToList())}");
}
}

string[] fRow = Console.ReadLine().Split(' ');
int N = int.Parse(fRow[0]);
int K = int.Parse(fRow[1]);
bool isChain = false;
int currentFirstIndex = -1;
int maxFirstIndex = -1;
int currentLastIndex = -1;
int maxLastIndex = -1;
int currentLength = 0;
int maxLength = 0;
int[] H = new int[N];
for (int i = 0; i < N; i++)
{
H[i] = int.Parse(Console.ReadLine());
if(H[i] > K)
{
if (isChain)
{
currentLastIndex = i;
}
else
{
currentFirstIndex = i;
isChain = true;
}
currentLength++;
}
else
{
if (maxLength < currentLength)
{
maxLength = currentLength;
maxFirstIndex = currentFirstIndex;
maxLastIndex = currentLastIndex;
}
currentLength = 0;
isChain = false;
}
}
Console.WriteLine("first: " + maxFirstIndex + " last: " + maxLastIndex);

This could be one of the way
static void Main(string[] args)
{
var firstLineInput = Console.ReadLine().Split(" ");
var numberOfInput = Int64.Parse(firstLineInput[0]);
var value = Int64.Parse(firstLineInput[1]);
var startIndex = -1; //No value greater than value
var endIndex = -1;
var maxLength = 0;
var maxStartIndex = -1;
var maxEndIndex = -1;
for (int i = 0; i < numberOfInput ; i++)
{
var input = Int64.Parse(Console.ReadLine());
if (input > value && startIndex == -1)
{
startIndex = i;
endIndex = i;
if(maxLength == 0)
{
maxLength = 1;
maxStartIndex = startIndex;
maxEndIndex = endIndex;
}
}
else if(input > value && startIndex != -1)
{
endIndex = i;
}
else if(input < value)
{
startIndex = -1;
endIndex = -1;
}
if (maxLength < (endIndex - startIndex))
{
maxLength = endIndex - startIndex;
maxStartIndex = startIndex;
maxEndIndex = endIndex;
}
}
Console.WriteLine($"{maxStartIndex} {maxEndIndex}");
}

Related

Divide an array's element by 2 for k times such that array's sum is minimized

I have an array of n integers and I need to divide any of it's elements by 2 (return the ceiling of the result) for k times such that the sum is minimum. The value of k can be very large as compared to n.
I am using this code:
private static int GetMaxSum(int[] array, int k)
{
int n = array.Length;
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(array);
if (array[indexAtMax] == 1) break;
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
return array.Sum();
}
private static int GetMaxIndex(int[] array)
{
int maxIndex = 0;
int max = array[0];
for (int i=1; i<array.Length;i++)
{
if (array[i] > max)
{
max = array[i];
maxIndex = i;
}
}
return maxIndex;
}
How can we improve the performance further probably by using max heap or some other data structure?
Unless I'm misunderstanding your requirements, your solution seens way too complicated (and apparently wrong according to comments).
I can't really think this through right now, but wouldn't it be the case that the global solution is made up of optimal intermediate steps? The order in which you divide is irrelevant and the problem is linear.
If that is the case, you simply have to evaluate the optimal division in each step and that is not very hard to do:
static void Minimize(int[] arr, int k)
{
for (var j = 0; j < k; j++)
{
var maxGainIndex = -1;
var maxGain = int.MinValue;
for (var i = 0; i < arr.Length; i++)
{
var gain = arr[i] - (arr[i]/2 + arr[i] % 2);
if (gain > maxGain)
{
maxGain = gain;
maxGainIndex = i;
}
}
arr[maxGainIndex] -= maxGain;
}
}
If I'm not wrong, the asymptotic behavior of this algorithm is O(k·n).
UPDATE:
Based on claims of posted code being far less optimal, I've taken the liberty of benchmarking both algorithms with these results on my machine:
Input array: 100;120;80;55;75;115;125;150;90;35;65;77;89;10;11;113;200;300
Number of divisions: 20
Running benchmarks in Release mode without debugger attached.
1000000 of GetMimimum finished in 584 ms with result 704.
1000000 of GetMimimum2 finished in 8846 ms with result 704.
Benchmarking code can be found here: https://dotnetfiddle.net/ITx53q
The performance gain of my proposed algorithm is rather staggering (x15), which was expected because your solution is, as evaluated initally, overcomplicated at best for such a simple problem.
As the assumption was that k>>n, the simpler algorithms are of the order O(kn) which can be too much of iterations.
I have written this code thinking of the problem and how can I limit sorting or calculating min/max. I have divided the array into subarrays so that the operations can be performed on subarrays without thinking of the order of operations.
private static int GetMinSum(int[] array, int k)
{
int n = array.Length;
var sum = 0;
k = GetOptimizedListAndK(array, n, k, out var lists);
//If more sublists are needed
if (k > 0)
{
var count = lists.CountSum;
var key = lists.Key;
if (key > 0)
{
var poweroftwo = 1 << key;
sum += count * poweroftwo - k * poweroftwo / 2;
var dictionary2 = GetDictionary(array, lists, poweroftwo);
key = dictionary2.Keys.Last();
while (k > 0 && key > 0)
{
var list2 = dictionary2[key];
count = list2.Count;
if (k >= count)
{
list2.ForEach(
index => array[index] = array[index] / 2 + array[index] % 2);
dictionary2.Remove(key);
key = dictionary2.Keys.LastOrDefault();
k -= count;
}
else
{
if (k <= Log2(count))
{
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(list2, array);
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
k = 0;
}
if (count - k <= Log2(count))
{
var minIndexes = GetMinIndexes(list2, array, count - k);
foreach (var i in list2)
{
if (!minIndexes.Contains(i))
{
array[i] = array[i] / 2 + array[i] % 2;
}
}
k = 0;
}
if (k > 0)
{
poweroftwo = 1 << key;
sum += list2.Count * poweroftwo - k * poweroftwo / 2;
dictionary2 = GetDictionary(array, list2, poweroftwo);
key = dictionary2.Keys.Last();
}
}
}
}
}
return array.Sum() + sum;
}
private static int GetOptimizedListAndK(int[] array, int n, int k, out Lists lists)
{
lists = null;
Dictionary<int, Lists> dictionary = new Dictionary<int, Lists>();
PopulatePowerBasedDictionary(array, n, dictionary);
var key = dictionary.Keys.Max();
while (key > 0 && k > 0)
{
lists = dictionary[key];
var count = lists.CountSum;
if (k >= count)
{
lists.ForEach(list => list.ForEach(index => array[index] = array[index] / 2 + array[index] % 2));
if (key > 1)
{
if (dictionary.TryGetValue(key - 1, out var lowerlists))
{
lowerlists.AddRange(lists);
lowerlists.CountSum += count;
}
else dictionary.Add((key - 1), lists);
}
dictionary.Remove(key);
key--;
k -= count;
}
else
{
if (k < Log2(count))
{
for (int i = 0; i < k; i++)
{
var indexAtMax = GetMaxIndex(lists, array);
array[indexAtMax] = array[indexAtMax] / 2 + array[indexAtMax] % 2;
}
k = 0;
}
if (count - k < Log2(count))
{
var minIndexes = GetMinIndexes(lists, array, count - k);
foreach (var list in lists)
{
foreach (var i in list)
{
if (!minIndexes.Contains(i))
{
array[i] = array[i] / 2 + array[i] % 2;
}
}
}
k = 0;
}
break;
}
}
return k;
}
private static void PopulatePowerBasedDictionary(int[] array, int n, Dictionary<int, Lists> dictionary)
{
for (int i = 0; i < n; i++)
{
if (array[i] < 2) continue;
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var lists))
{
lists[0].Add(i);
lists.CountSum++;
}
else
{
lists = new Lists(1,log2) { new List<int> { i } };
dictionary.Add(log2, lists);
}
}
}
private static int GetMaxIndex(List<int> list, int[] array)
{
var maxIndex = 0;
var max = 0;
foreach (var i in list)
{
if (array[i] > max)
{
maxIndex = i;
max = array[i];
}
}
return maxIndex;
}
private static SortedDictionary<int, List<int>> GetDictionary(int[] array, Lists lists, int poweroftwo)
{
SortedDictionary<int, List<int>> dictionary = new SortedDictionary<int, List<int>>();
foreach (var list in lists)
{
foreach (var i in list)
{
array[i] = array[i] - poweroftwo;
if (array[i] < 2)
{
continue;
}
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var list2))
{
list2.Add(i);
}
else
{
list2 = new List<int> { i };
dictionary.Add(log2, list2);
}
}
}
return dictionary;
}
private static SortedDictionary<int, List<int>> GetDictionary(int[] array, List<int> list, int poweroftwo)
{
SortedDictionary<int, List<int>> dictionary = new SortedDictionary<int, List<int>>();
foreach (var i in list)
{
array[i] = array[i] - poweroftwo;
if (array[i] < 2)
{
continue;
}
var log2 = Log2(array[i]);
if (dictionary.TryGetValue(log2, out var list2))
{
list2.Add(i);
}
else
{
list2 = new List<int> { i };
dictionary.Add(log2, list2);
}
}
return dictionary;
}
private static int GetMaxIndex(Lists lists, int[] array)
{
var maxIndex = 0;
var max = 0;
foreach (var list in lists)
{
foreach (var i in list)
{
if (array[i]>max)
{
maxIndex = i;
max = array[i];
}
}
}
return maxIndex;
}
private static HashSet<int> GetMinIndexes(Lists lists, int[] array, int k)
{
var mins = new HashSet<int>();
var minIndex = 0;
var min = int.MaxValue;
for (int j = 0; j < k; j++)
{
foreach (var list in lists)
{
foreach (var i in list)
{
if (array[i] < min && !mins.Contains(i))
{
minIndex = i;
min = array[i];
}
}
}
mins.Add(minIndex);
min = int.MaxValue;
}
return mins;
}
private static HashSet<int> GetMinIndexes(List<int> list, int[] array, int k)
{
var mins = new HashSet<int>();
var minIndex = 0;
var min = int.MaxValue;
for (int j = 0; j < k; j++)
{
foreach (var i in list)
{
if (array[i] < min && !mins.Contains(i))
{
minIndex = i;
min = array[i];
}
}
mins.Add(minIndex);
min = int.MaxValue;
}
return mins;
}
private static int Log2(int n)
{
return BitOperations.Log2((uint)n);
}
Lists Class:
public class Lists:List<List<int>>
{
public int Key { get; set; }
public int CountSum { get; set; }
public Lists(int countSum, int key):base()
{
CountSum = countSum;
Key = key;
}
}

Hackerrank: Climbing the Leaderboard

i have a deal with a hackerrank algorithm problem.
It works at all cases, except 6-7-8-9. It gives timeout error. I had spent so much time at this level. Someone saw where is problem?
static long[] climbingLeaderboard(long[] scores, long[] alice)
{
//long[] ranks = new long[scores.Length];
long[] aliceRanks = new long[alice.Length]; // same length with alice length
long lastPoint = 0;
long lastRank;
for (long i = 0; i < alice.Length; i++)
{
lastPoint = scores[0];
lastRank = 1;
bool isIn = false; // if never drop in if statement
for (long j = 0; j < scores.Length; j++)
{
if (lastPoint != scores[j]) //if score is not same, raise the variable
{
lastPoint = scores[j];
lastRank++;
}
if (alice[i] >= scores[j])
{
aliceRanks[i] = lastRank;
isIn = true;
break;
}
aliceRanks[i] = !isIn & j + 1 == scores.Length ? ++lastRank : aliceRanks[i]; //drop in here
}
}
return aliceRanks;
}
This problem can be solved in O(n) time, no binary search needed at all. First, we need to extract the most useful piece of data given in the problem statement, which is,
The existing leaderboard, scores, is in descending order.
Alice's scores, alice, are in ascending order.
An approach that makes this useful is to create two pointers, one at the start of alice array, let's call it "i", and the second is at the end of scores array, let's call it "j". We then loop until i reaches the end of alice array and at each iteration, we check for three main conditions. We increment i by one if alice[i] is less than scores[j] because the next element of alice may be also less than the current element of scores, or we decrement j if alice[i] is greater than scores[j] because we are sure that the next elements of alice are also greater than those elements discarded in scores. The last condition is that if alice[i] == scores[j], we only increment i.
I solved this question in C++, my goal here is to make you understand the algorithm, I think you can easily convert it to C# if you understand it. If there are any confusions, please tell me. Here is the code:
// Complete the climbingLeaderboard function below.
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice) {
int j = 1, i = 1;
// this is to remove duplicates from the scores vector
for(i =1; i < scores.size(); i++){
if(scores[i] != scores[i-1]){
scores[j++] = scores[i];
}
}
int size = scores.size();
for(i = 0; i < size-j; i++){
scores.pop_back();
}
vector<int> ranks;
i = 0;
j = scores.size()-1;
while(i < alice.size()){
if(j < 0){
ranks.push_back(1);
i++;
continue;
}
if(alice[i] < scores[j]){
ranks.push_back(j+2);
i++;
} else if(alice[i] > scores[j]){
j--;
} else {
ranks.push_back(j+1);
i++;
}
}
return ranks;
}
I think this may help you too:
vector is like an array list that resizes itself.
push_back() is inserting at the end of the vector.
pop_back() is removing from the end of the vector.
Here is my solution with c#
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> result = new List<int>();
ranked = ranked.Distinct().ToList();
var pLength = player.Count;
var rLength = ranked.Count-1;
int j = rLength;
for (int i = 0; i < pLength; i++)
{
for (; j >= 0; j--)
{
if (player[i] == ranked[j])
{
result.Add(j + 1);
break;
}
else if(player[i] < ranked[j])
{
result.Add(j + 2);
break;
}
else if(player[i] > ranked[j]&&j==0)
{
result.Add(1);
break;
}enter code here
}
}
return result;
}
Here is a solution that utilizes BinarySearch. This method returns the index of the searched number in the array, or if the number is not found then it returns a negative number that is the bitwise complement of the index of the next element in the array. Binary search only works in sorted arrays.
public static int[] GetRanks(long[] scores, long[] person)
{
var defaultComparer = Comparer<long>.Default;
var reverseComparer = Comparer<long>.Create((x, y) => -defaultComparer.Compare(x, y));
var distinctOrderedScores = scores.Distinct().OrderBy(i => i, reverseComparer).ToArray();
return person
.Select(i => Array.BinarySearch(distinctOrderedScores, i, reverseComparer))
.Select(pos => (pos >= 0 ? pos : ~pos) + 1)
.ToArray();
}
Usage example:
var scores = new long[] { 100, 100, 50, 40, 40, 20, 10 };
var alice = new long[] { 5, 25, 50, 120 };
var ranks = GetRanks(scores, alice);
Console.WriteLine($"Ranks: {String.Join(", ", ranks)}");
Output:
Ranks: 6, 4, 2, 1
I was bored so i gave this a go with Linq and heavily commented it for you,
Given
public static IEnumerable<int> GetRanks(long[] scores, long[] person)
// Convert scores to a tuple
=> scores.Select(s => (scores: s, isPerson: false))
// convert persons score to a tuple and concat
.Concat(person.Select(s => (scores: s, isPerson: true)))
// Group by scores
.GroupBy(x => x.scores)
// order by score
.OrderBy(x => x.Key)
// select into an indexable tuple so we know everyones rank
.Select((groups, i) => (rank: i, groups))
// Filter the person
.Where(x => x.groups.Any(y => y.isPerson))
// select the rank
.Select(x => x.rank);
Usage
static void Main(string[] args)
{
var scores = new long[]{1, 34, 565, 43, 44, 56, 67};
var alice = new long[]{578, 40, 50, 67, 6};
var ranks = GetRanks(scores, alice);
foreach (var rank in ranks)
Console.WriteLine(rank);
}
Output
1
3
6
8
10
Based on the given constraint brute-force solution will not be efficient for the problem.
you have to optimize your code and the key part here is to look up for exact place which can be effectively done by using binary search.
Here is the solution using binary search:-
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int n = scores.length;
int m = alice.length;
int res[] = new int[m];
int[] rank = new int[n];
rank[0] = 1;
for (int i = 1; i < n; i++) {
if (scores[i] == scores[i - 1]) {
rank[i] = rank[i - 1];
} else {
rank[i] = rank[i - 1] + 1;
}
}
for (int i = 0; i < m; i++) {
int aliceScore = alice[i];
if (aliceScore > scores[0]) {
res[i] = 1;
} else if (aliceScore < scores[n - 1]) {
res[i] = rank[n - 1] + 1;
} else {
int index = binarySearch(scores, aliceScore);
res[i] = rank[index];
}
}
return res;
}
private static int binarySearch(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] == key) {
return mid;
} else if (a[mid] < key && key < a[mid - 1]) {
return mid;
} else if (a[mid] > key && key >= a[mid + 1]) {
return mid + 1;
} else if (a[mid] < key) {
hi = mid - 1;
} else if (a[mid] > key) {
lo = mid + 1;
}
}
return -1;
}
You can refer to this link for a more detailed video explanation.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int[] uniqueScores = IntStream.of(scores).distinct().toArray();
int [] rank = new int [alice.length];
int startIndex=0;
for(int j=alice.length-1; j>=0;j--) {
for(int i=startIndex; i<=uniqueScores.length-1;i++) {
if (alice[j]<uniqueScores[uniqueScores.length-1]){
rank[j]=uniqueScores.length+1;
break;
}
else if(alice[j]>=uniqueScores[i]) {
rank[j]=i+1;
startIndex=i;
break;
}
else{continue;}
}
}
return rank;
}
My solution in javascript for climbing the Leaderboard Hackerrank problem. The time complexity of the problem can be O(i+j), i is the length of scores and j is the length of alice. The space complexity is O(1).
// Complete the climbingLeaderboard function below.
function climbingLeaderboard(scores, alice) {
const ans = [];
let count = 0;
// the alice array is arranged in ascending order
let j = alice.length - 1;
for (let i = 0 ; i < scores.length ; i++) {
const score = scores[i];
for (; j >= 0 ; j--) {
if (alice[j] >= score) {
// if higher than score
ans.unshift(count+1);
} else if (i === scores.length - 1) {
// if smallest
ans.unshift(count+2);
} else {
break;
}
}
// actual rank of the score in leaderboard
if (score !== scores[i-1]) {
count++;
}
}
return ans;
}
Here is my solution
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
for (int i = 0; i < distinct.Count; i++)
{
if (item == distinct[i])
{
rank.Add(i + 1);
break;
}
}
}
return rank;
This can be modified by removing the inner for loop also
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
var index = ranked.FindIndex(x => x == item);
rank.Add(index + 1);
}
return rank;
This is my solution in c# for Hackerrank Climbing the Leaderboard based on C++ answer here.
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> _ranked = new List<int>();
_ranked.Add(ranked[0]);
for(int a=1; a < ranked.Count(); a++)
if(_ranked[_ranked.Count()-1] != ranked[a])
_ranked.Add(ranked[a]);
int j = _ranked.Count()-1;
int i = 0;
while(i < player.Count())
{
if(j < 0)
{
player[i] = 1;
i++;
continue;
}
if(player[i] < _ranked[j])
{
player[i] = j+2;
i++;
}
else
if(player[i] == _ranked[j])
{
player[i] = j+1;
i++;
}
else
{
j--;
}
}
return player;
}
My solution in Java for climbing the Leaderboard Hackerrank problem.
// Complete the climbingLeaderboard function below.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
Arrays.sort(scores);
HashSet<Integer> set = new HashSet<Integer>();
int[] ar = new int[alice.length];
int sc = 0;
for(int i=0; i<alice.length; i++){
sc = 1;
set.clear();
for(int j=0; j<scores.length; j++){
if(alice[i] < scores[j] && !set.contains(scores[j])){
sc++;
set.add(scores[j]);
}
}
ar[i] = sc;
}return ar;
}

C# Adding big numbers using only strings?

I am trying to write a program that sums very big numbers (I am trying to solve a problem on projecteuler.net), so I cannot parse them into number types. So I was wondering if it is possible to sum such numbers using only strings or something like that?
Try using BigInteger instead. It effictively lets you use integers of arbitrary size.
kindly use BigInteger found in System.Numerics and use `
Add(BigInteger, BigInteger)
` please follow the below link for better understanding.
add two bigintegers
BigInteger Represents an arbitrarily large signed integer. microsoft documentation.
class Program
{
static void Main(string[] args)
{
string inputString = Console.ReadLine();
string[] linePart = inputString.Split(' ', ',', '\n'); // split as , and " " and new line
/* Console.WriteLine(linePart[1]);*/
string num0 = linePart[0];
string num1 = linePart[1];
int val0 = num0.Length;
int iv0 = val0;
int val1 = num1.Length;
int iv1 = val1;
/* Console.WriteLine(val0);
Console.WriteLine(val1)*/;
int arraySize;
if (val0 > val1)
{
arraySize = val0;
}
else { arraySize = val1; }
int[] arr0 = new int[arraySize];
int[] arr1 = new int[arraySize];
for (int i =0; i <iv0; i++)
{
arr0[i] = num0[val0-1]-48;
val0--;
}
for (int i = 0; i < iv1; i++)
{
arr1[i] = num1[val1-1]-48;
val1--;
}
/* for (int i = 0; i < arraySize; i++)
{
Console.Write(arr0[i]);
Console.Write(" ");
Console.Write(arr1[i]);
Console.WriteLine();
}*/
int tamp=0;
int rem=0;
int[] ans = new int[arraySize+1];
int ansloop = arraySize;
for(int i = 0; i <= arraySize; i++)
{
if (i != arraySize)
{
tamp = arr0[i] + arr1[i];
tamp = tamp + rem;
if (tamp >= 10)
{
tamp = tamp % 10;
rem = 1;
}
else { rem = 0; }
ans[ansloop] = tamp;
ansloop--;
}
else {
ans[ansloop] = rem;
}
}
for (int i = 0; i <= arraySize; i++)
{
Console.Write(ans[i]+" ");
}
}
}
}

Digit difference sort

So I am trying to solve this task "Digit Difference Sort" on Codefights
Given an array of integers, sort its elements by the difference of their largest and smallest digits.
In the case of a tie, that with the larger index in the array should come first.
Example
For a = [152, 23, 7, 887, 243], the output should be digitDifferenceSort(a) = [7, 887, 23, 243, 152].
Here are the differences of all the numbers:
152: difference = 5 - 1 = 4;
23: difference = 3 - 2 = 1;
7: difference = 7 - 7 = 0;
887: difference = 8 - 7 = 1;
243: difference = 4 - 2 = 2.
23 and 887 have the same difference, but 887 goes after 23 in a, so in the sorted array it comes first.
I have an issue with two numbers having the same difference. Here's what I wrote so far:
int[] digitDifferenceSort(int[] a) {
return a.OrderBy(x => difference(x)).ToArray();
}
int difference(int x)
{
int min = 9, max = 0;
do
{
int tmp = x % 10;
min = Math.Min(min, tmp);
max = Math.Max(max, tmp);
} while ((x /= 10) > 0);
return max - min;
}
Didn't do much (for example the output is still [7, 23, 887, 243, 152] rather than [7, 887, 23, 243, 152])
How do I make element with larger index come first in result? What should I use instead of OrderBy?
I don't consider your difference method, i assume it works fine.
To your question: you have to keep revered order of the array (that the items with the same difference arrive will be sorted reverse). To do it, you could just reverse you input array: all items with not identical difference will be ordered correctly, and with the same differece will be ordered reversed:
int[] digitDifferenceSort(int[] a)
{
return a.Reverse().OrderBy(x => difference(x)).ToArray();
}
Following is my code for the above question digit difference sort. I am also getting output when running in Eclipse but when I paste the code on code signal it gives me a null pointer exception.
package NormalPrograms;
import java.util.ArrayList;
import java.util.Collections;
public class DigitDifferenceSort {
// For index wise sorting in descending order
public static int[] sortingnumberindexwise(int[] a, ArrayList<Integer> index) {
int k = 0;
int[] res = new int[index.size()];
int[] finalres = new int[index.size()];
for (int i = a.length - 1; i >= 0; i--) {
for (int j = 0; j < index.size(); j++) {
if (a[i] == (int) index.get(j)) {
res[k] = i;
index.remove(j);
k++;
break;
}
}
}
int g = 0;
k = 0;
for (int i = 0; i < res.length; i++) {
finalres[g] = a[res[k]];
g++;
k++;
}
return finalres;
}
public static int[] finddigitDifferenceandSort(int[] p) {
int[] finres = new int[p.length];
for (int i = 0; i < finres.length; i++) {
finres[i] = p[i];
}
// This finres array act as an temp array and reused to make final result array
int digit = 0;
ArrayList<Integer> A = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> B = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++) {
B.add(new ArrayList<Integer>());
}
for (int i = 0; i < p.length; i++) {
int temp = 0;
temp = p[i];
while (p[i] > 0) {
digit = p[i] % 10;
p[i] /= 10;
A.add(digit);
}
int b = Collections.max(A);
int c = Collections.min(A);
int diff = b - c;
B.get(diff).add(temp);
A.clear();
}
for (int i = 0; i < B.size(); i++) {
if (B.get(i).size() > 1) {
ArrayList<Integer> C = new ArrayList<Integer>();
for (int k = 0; k < B.get(i).size(); k++) {
C.add(B.get(i).get(k));
}
B.get(i).clear();
for (int j : sortingnumberindexwise(finres, C)) {
B.get(i).add(j);
}
} else {
continue;
}
}
int k = 0;
for (int i = 0; i < B.size(); i++) {
for (int j = 0; j < B.get(i).size(); j++) {
if (B.get(i).size() == 0)
continue;
else {
finres[k] = B.get(i).get(j);
k++;
}
}
}
return finres;
}
public static void main(String[] args) {
int[] a = { 12, 21, 1, 1, 1, 2, 2, 3 };
for (int i : finddigitDifferenceandSort(a)) {
System.out.print(i + " ");
}
}
}

How to find the maximal (longest) sequence of increasing elements in an array arr[n]?

I need to write a program, which finds the maximal sequence of increasing elements in an array arr[n]. It is not necessary the elements to be consecutively placed. E.g.: {9, 6, 2, 7, 4, 7, 6, 5, 8, 4} -> {2, 4, 6, 8}.
I have some guidelines to use 2 nested loops and one additional array.
So far i know how to use if statements, loops and little arrays.
Any suggestions pls...?
This is my start so far (am I on a good track?):
Console.Write("Elements in array: ");
int n = int.Parse(Console.ReadLine());
int[] arr = new int[n];
int[] result;
for (int index = 0; index < arr.Length; index++)
{
Console.Write("Array [{0}] = ", index);
arr[index] = int.Parse(Console.ReadLine());
}
for (int indexOut = 0; indexOut < n; indexOut++)
{
for (int indexIn = 1; indexIn < n; indexIn++)
{
}
}
nested loops are 1 loop inside another:
for (int 1 = 0; i < something.length; i++) {
for ( int j = 0; j < somethingElse.length; j++) {
// code
}
}
I think I found your solution here:
http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/
/* Dynamic Programming C/C++ implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>
/* lis() returns the length of the longest increasing
subsequence in arr[] of size n */
int lis( int arr[], int n )
{
int *lis, i, j, max = 0;
lis = (int*) malloc ( sizeof( int ) * n );
/* Initialize LIS values for all indexes */
for ( i = 0; i < n; i++ )
lis[i] = 1;
/* Compute optimized LIS values in bottom up manner */
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
/* Pick maximum of all LIS values */
for ( i = 0; i < n; i++ )
if ( max < lis[i] )
max = lis[i];
/* Free memory to avoid memory leak */
free( lis );
return max;
}
/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of LIS is %d\n", lis( arr, n ) );
return 0;
}
You will have to modify it a little to generate the actual array.
My code:
// Arr[]
int n = 10;
int[] arr = new int[n];
for (int index = 0; index < n; index++)
{
Console.Write("Array[{0}] = ", index);
arr[index] = int.Parse(Console.ReadLine());
}
// Len[]
int[] len = new int[n];
for (int index = 0; index < n; index++)
{
len[index] = 1;
}
// Correct len[]
for (int indexCount = 1; indexCount < n; indexCount++)
{
for (int indexNumber = 0; indexNumber < indexCount; indexNumber++)
{
if (arr[indexCount] > arr[indexNumber] && len[indexCount] < len[indexNumber] + 1)
{
len[indexCount] = len[indexNumber] + 1;
}
}
}
// Print new len[]
// Just to keep track of numbers
Console.WriteLine();
Console.Write("{");
for (int index = 0; index < n; index++)
{
Console.Write(" " + len[index] + " ");
}
Console.WriteLine("}");
// Search for the max number in len[]
int max = int.MinValue;
int maxPosition = 0;
for (int index = 0; index < len.Length; index++)
{
if (len[index] > max)
{
max = len[index];
maxPosition = index;
}
}
// Create the result in result[]
int[] result = new int[max];
int i = (max - 1);
int maxCount = max;
for (int index = maxPosition; index >= 0; index--)
{
if (len[index] == max)
{
result[i] = arr[index];
max--;
i--;
}
}
// Print the result[]
Console.WriteLine();
Console.Write("{");
for (int index = 0; index < maxCount; index++)
{
Console.Write(" " + result[index] + " ");
}
Console.WriteLine("}");
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int maincount = 0;
int indices = 0;
int increment = 0;
int count = 0;
int finalcount = 0;
int checkvalue = 0;
string consincval = null;
string consincval1 = null;
string finalconsincval = null;
Console.WriteLine("Enter number of rows of the array");
int len = int.Parse(Console.ReadLine());
Console.WriteLine("Enter number of columns of the array");
int wid = int.Parse(Console.ReadLine());
int[,] consecincrease = new int[len, wid];
Console.WriteLine("Enter the Values of array");
for (int index = 0; index < consecincrease.GetLength(0); index++)
{
for (int index1 = 0; index1 < consecincrease.GetLength(1); index1++)
{
consecincrease[index, index1] = int.Parse(Console.ReadLine());
Console.Write("The value of the {0} {1}" + ":" + " " + "{2}", index, index1, consecincrease[index, index1]);
Console.WriteLine();
}
}
for (int index = 0; index < consecincrease.GetLength(0); index++)
{
for (int index1 = 0; index1 < consecincrease.GetLength(1); index1++)
{
increment = 0;
checkvalue = consecincrease[index, index1];
for ( indices = increment; indices < consecincrease.GetLength(1)-1; indices++)
{
if (checkvalue < consecincrease[index, indices +1])
{
consincval = Convert.ToString(checkvalue);
count++;
maincount = count;
checkvalue = consecincrease[index, indices+1];
consincval1 = consincval1 + " " + consincval + " ";
}
}
if (count == 0)
{
}
else if (count >= 1)
{
consincval = Convert.ToString(checkvalue);
count++;
maincount = count;
consincval1 = consincval1 + " " + consincval + " ";
}
if (finalcount < maincount)
{
finalcount = maincount;
finalconsincval = consincval1;
count = 0;
consincval1 = null;
consincval = null;
}
else
{
count = 0;
consincval1 = null;
consincval = null;
}
increment ++;
}
}
Console.WriteLine();
Console.WriteLine(finalconsincval);
Console.ReadLine();
}
}
}

Categories

Resources