Counting alternating numbers in an array - c#

Given an array of integers...
var numbers = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
I need to determine a the maximum sequence of numbers that alternate up then down or down then up.
Not sure the best way to approach this, the process psuedo wise strikes me as simple but materializing code for it is evading me.
The key is the fact we are looking for max sequence, so while the above numbers could be interpreted in many ways, like a sequence of seven up-down-up and seven down-up-down the important fact is starting with the first number there is a down-up-down sequence that is 14 long.
Also I should not that we count the first item, 121 is a sequence of length 3, one could argue the sequence doesn't begin until the second digit but lets not split hairs.

This seems to work, it assumes that the length of numbers is greater than 4 (that case should be trivial anyways):
var numbers = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
int count = 2, max = 0;
for (int i = 1; i < numbers.Length - 1; i++)
{
if ((numbers[i - 1] < numbers[i] && numbers[i + 1] < numbers[i]) ||
(numbers[i - 1] > numbers[i] && numbers[i + 1] > numbers[i]))
{
count++;
max = Math.Max(count, max);
}
else if ((numbers[i - 1] < numbers[i]) || (numbers[i - 1] > numbers[i])
|| ((numbers[i] < numbers[i + 1]) || (numbers[i] > numbers[i + 1])))
{
max = Math.Max(max, 2);
count = 2;
}
}
Console.WriteLine(max); // 14

Here's how I thought of it
First, you need to know whether you're starting high or starting low. eg: 1-2-1 or 2-1-2. You might not even have an alternating pair.
Then, you consider each number afterwards to see if it belongs in the sequence, taking into consideration the current direction.
Everytime the sequence breaks, you need to start again by checking the direction.
I am not sure if it is possible that out of the numbers you have already seen, picking a different starting number can POSSIBLY generate a longer sequence. Maybe there is a theorem that shows it is not possible; maybe it is obvious and I am over-thinking. But I don't think it is possible since the reason why a sequence is broken is because you have two high's or two low's and there is no way around this.
I assumed the following cases
{} - no elements, returns 0
{1} - single element, returns 0
{1, 1, 1} - no alternating sequence, returns 0
No restriction on the input beyond what C# expects. It could probably be condensed. Not sure if there is a way to capture the direction-change logic without explicitly keeping track of the direction.
static int max_alternate(int[] numbers)
{
int maxCount = 0;
int count = 0;
int dir = 0; // whether we're going up or down
for (int j = 1; j < numbers.Length; j++)
{
// don't know direction yet
if (dir == 0)
{
if (numbers[j] > numbers[j-1])
{
count += 2; // include first number
dir = 1; // start low, up to high
}
else if (numbers[j] < numbers[j-1])
{
count += 2;
dir = -1; // start high, down to low
}
}
else
{
if (dir == -1 && numbers[j] > numbers[j-1])
{
count += 1;
dir = 1; // up to high
}
else if (dir == 1 && numbers[j] < numbers[j-1])
{
count += 1;
dir = -1; // down to low
}
else
{
// sequence broken
if (count > maxCount)
{
maxCount = count;
}
count = 0;
dir = 0;
}
}
}
// final check after loop is done
if (count > maxCount)
{
maxCount = count;
}
return maxCount;
}
And some test cases with results based on my understanding of the question and some assumptions.
static void Main(string[] args)
{
int[] nums = { 1}; // base case == 0
int[] nums2 = { 2, 1 }; // even case == 2
int[] nums3 = { 1, 2, 1 }; // odd case == 3
int[] nums4 = { 2, 1, 2 }; // flipped starting == 3
int[] nums5 = { 2, 1, 2, 2, 1, 2, 1 }; // broken seqeuence == 4
int[] nums6 = { 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1 }; // long sequence == 14
Console.WriteLine(max_alternate(nums));
Console.WriteLine(max_alternate(nums2));
Console.WriteLine(max_alternate(nums3));
Console.WriteLine(max_alternate(nums4));
Console.WriteLine(max_alternate(nums5));
Console.WriteLine(max_alternate(nums6));
Console.ReadLine();
}

I'm not from a pc with a compiler right now, so I just give a try:
int max = 0;
int aux =0;
for(int i = 2 ; i < length; ++i)
{
if (!((numbers[i - 2] > numbers[i - 1] && numbers[i - 1] < numbers[i]) ||
numbers[i - 2] < numbers[i - 1] && numbers[i - 1] > numbers[i]))
{
aux = i - 2;
}
max = Math.Max(i - aux,max);
}
if (max > 0 && aux >0)
++max;
Note: should works for sequence of at least 3 elements.

There are probably a lot of ways to approach this, but here is one option:
var numbers = new int[] { 7,1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1 };
int maxCount = 0;
for (int j = 0; j+1 < numbers.Length; j++)
{
int count = 0;
if (numbers[j] < numbers[j+1])
{
count += 2;
for (int i = j+2; i+1 < numbers.Length; i += 2)
{
if (numbers[i] < numbers[i + 1] )
{
count += 2;
}
else
{
break;
}
}
}
if (maxCount < count)
{
maxCount = count;
}
}
Console.WriteLine(maxCount);
Console.ReadLine();
This solution assumes that you want a sequence of the same two alternating numbers. If that's not a requirement you could alter the second if.
Now that it's written out, it looks more complex than I had imagined in my head... Maybe someone else can come up with a better solution.

Assumes at least 2 elements.
int max = 1;
bool expectGreaterThanNext = (numbers[0] > numbers[1]);
int count = 1;
for (var i = 0; i < numbers.Length - 1; i++)
{
if (numbers[i] == numbers[i + 1] || expectGreaterThanNext && numbers[i] < numbers[i + 1])
{
count = 1;
expectGreaterThanNext = (i != numbers.Length - 1) && !(numbers[i] > numbers[i+1]);
continue;
}
count++;
expectGreaterThanNext = !expectGreaterThanNext;
max = Math.Max(count, max);
}

This works for any integers, it tracks low-hi-low and hi-low-hi just like you asked.
int numbers[] = new int[] { 1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,1,2,1 };
int count = 0;
int updownup = 0;
int downupdown = 0;
for(int x = 0;x<=numbers.Length;x++)
{
if(x<numbers.Length - 2)
{
if(numbers[x]<numbers[x+1])
{
if(numbers[x+1]>numbers[x+2])
{
downupdown++;
}
}
}
}
count = 0;
for(x=0;x<=numbers.Length;x++)
{
if(x<numbers.Length - 2)
{
if(numbers[x]>numbers[x+1]
{
if(numbers[x+1]<numbers[x+2])
{
updownup++;
}
}
}
}

Related

How to remove two elements of collection at the same time? Task about cyclopes lenses

I cant solve this task.
There are N cyclopes and an array of N elements.
Every element is eyesight value of single cyclop.
Every cyclop needs a lens with a value K but he will be okay with
lens of value K+1 or K-1.
Cyclopes always buy lenses in pairs.
For example 5 cyclopes with eyesight values [1,-1,2,3,-3] will need to buy 3 pairs of lenses.
I need to write a program that will count minimal amount of lens pairs need.
I tried it like this
int cyclops = 4;
int[] cyclopsSightValues = { 1, 7, 4, 1 };
if (cyclops < 2) { return 1;}
List<int> list = cyclopsSightValues .ToList();
int matchCount = 0;
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < list.Count; j++)
{
if (list[i] == list[j] ||
list[i] + 1 == list[j] ||
list[i] + 2 == list[j] ||
list[i] - 1 == list[j] ||
list[i] - 2 == list[j])
{
int valueToRemove1 = list[i];
int valueToRemove2 = list[j];
list.Remove(valueToRemove1);
list.Remove(valueToRemove2);
matchCount++;
continue;
}
}
}
return matchCount + (cyclops-matchCount*2);
I think i need to find matching eyesights and remove them from list, but the result always comes out less then the correct one by 1.
Maybe my logic is wrong altogether?
Any help would be much appreciated.
Look, if two cyclops have eyesight difference 2 or less by absolute value they can buy lenses which fit both of them, e.g.
3 and 1 can buy pair of 2 lenses. Let's try to use greedy approach now: order cyclops by their eye sights and try
to use spare lenses as frequent as we could:
1, -1, 2, 3, -3 -> -3, -1, 1, 2, 3
-3 v -1, 1 v 2, 3
can use
-2 1
So far so good all we have to do is to sort and scan:
private static int Solve(int[] cyclopsSightValues) {
Array.Sort(cyclopsSightValues);
int result = 0;
bool hasSpare = false;
for (int i = 0; i < cyclopsSightValues.Length; ++i)
if (hasSpare && cyclopsSightValues[i - 1] + 2 >= cyclopsSightValues[i])
hasSpare = false; // We use spare lense from the previous cyclope
else {
// we have to buy a pair, and now we have a spare lense
hasSpare = true;
result += 1;
}
return result;
}
Demo:
int[][] tests = {
new[] { 1, -1, 2, 3, -3 },
new int[] { },
new[] { 1, 1, 1, 1 },
};
string report = string.Join(Environment.NewLine, tests
.Select(item => $"[{string.Join(", ", item)}] => {Solve(item)}"));
Console.Write(report);
Output:
[1, -1, 2, 3, -3] => 3
[] => 0
[1, 1, 1, 1] => 2
Please, fiddle yourself
Untested, but should more or less work:
public static IEnumerable<int> LensesToBuy(IEnumerable<int> cyclopsVisions)
{
int? buf = null;
var e = cyclopsVisions.OrderBy(v => v).GetEnumerator();
while(e.MoveNext())
{
if (!buf.HasValue)
{
buf = e.Current;
}
else if (Math.Abs(buf.Value - e.Current) > 2)
{ // cached value not compatible
yield return buf.Value;
buf = e.Current;
}
else
{ // cached value is compatible
if (buf.Value == e.Current) yield return buf.Value;
if (buf.Value > e.Current) yield return buf.Value - 1;
if (buf.Value < e.Current) yield return buf.Value + 1;
buf = null;
}
}
if (buf.HasValue) yield return buf.Value;
}
Call it like this:
int[] cyclopsSightValues = { 1, 7, 4, 1 };
var result = LensesToBuy(cyclopsSightValues); //okay to pass array
Console.WriteLine(result.Count());

MaxCounters codility understanding

I have wanted to try some challenges on Codility and started from beginning. All assignments were relatively easy up to the one called MaxCounters. I do not believe that this one is especially hard although it is the first one marked as not painless.
I have read the task and started coding in C# language:
public static int[] maxPart(int N, int[] A){
int[] counters = new int[N];
for(int i = 0; i < A.Length; i++){
for(int j = 0; j < counters.Length; j++){
if(A[i] == counters[j] && (counters[j] >= 1 && counters[j] <= N )){
counters [j] = counters [j] + 1;
}
if(A[i] == N + 1 ){
int tmpMax = counters.Max ();
for(int h = 0; h < counters.Length; h++){
counters [h] = tmpMax;
}
}
}
}
return counters;
}
Having 3 loops of course makes it really slow, but lets leave it for later. My concern is how I understood this like this and all the other people see it like on this question here.
From the assignment's description.
it has 2 actions:
increase(X) − counter X is increased by 1,
max counter − all counters are set to the maximum value of any
counter.
which occur under conditions:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max counter.
Both conditions are stated in the code above. Obviusly it is wrong but I am confused, and I do not know how could I understand it differently.
Why is this code wrong, what am I missing from task description?
One of the top rated answers looks like this:
public int[] solution(int N, int[] A) {
int[] result = new int[N];
int maximum = 0;
int resetLimit = 0;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
throw new InvalidOperationException();
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetLimit) {
result[A[K] - 1] = resetLimit + 1;
} else {
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
// inefficiency here
//for (int i = 0; i < result.Length; i++)
// result[i] = maximum;
resetLimit = maximum;
}
}
for (int i = 0; i < result.Length; i++)
result[i] = Math.max(resetLimit, result[i]);
return result;
}
This code results with 100% on Codility.
Question:
I would like to know how the author knew from the task to use result[A[K] - 1]? What would resetLimit represent?
Maybe I completely misunderstood the question due to my English I am not sure. I just can not go over it.
EDIT:
Based on my code provided, how did I misunderstood the assignment? Generally I am asking for explanation of the problem. Whether to explain what needs to be done, or take the code as correct result and provide and explanation why is this done this way?
In my opinion you somehow mixed the index of the counter (values in A) and the value of the counter (values in counter). So there is no magic in using A[i]-1 - it is the value X from the problem description (adjusted to 0-based index).
My naive approach would be, the way I understood the problem (I hope it makes clear, what your code is doing wrong):
public static int[] maxPart(int N, int[] A){
int[] counters = new int[N];
for(int i = 0; i < A.Length; i++){
int X=A[i];
if(X>=1 && X<=N){ // this encodes increment(X), with X=A[i]
counters [X-1] = counters [X-1] + 1; //-1, because our index is 0-based
}
if(X == N + 1 ){// this encodes setting all counters to the max value
int tmpMax = counters.Max ();
for(int h = 0; h < counters.Length; h++){
counters [h] = tmpMax;
}
}
}
}
return counters;
}
Clearly, this would be too slow as the complexity isO(n^2) with n=10^5 number of operations (length of the array A), in the case of the following operation sequence:
max counter, max counter, max counter, ....
The top rated solution solves the problem in a lazy manner and does not update all values explicitly every time a max counter operation is encountered, but just remembers which minimal value all counters must have after this operation in resetLimit. Thus, every time he must increment a counter, he looks up whether its value must be updated due to former max counter operations and makes up for all max counter operation he didn't execute on this counter
if(result[A[K] - 1] < resetLimit) {
result[A[K] - 1] = resetLimit + 1;
}
His solution runs in O(n) and is fast enough.
Here is my solution in JavaScript.
const maxCounters = (N, A) => {
for (let t = 0; t < A.length; t++) {
if (A[t] < 1 || A[t] > N + 1) {
throw new Error('Invalid input array A');
}
}
let lastMaxCounter = 0; // save the last max counter is applied to all counters
let counters = []; // counters result
// init values by 0
for (let i = 0; i < N; i++) {
counters[i] = 0;
}
let currentMaxCounter = 0; // save the current max counter each time any counter is increased
let maxApplied = false;
for (let j = 0; j < A.length; j++) {
const val = A[j];
if (1 <= val && val <= N) {
if (maxApplied && counters[val - 1] < lastMaxCounter) {
counters[val - 1] = lastMaxCounter;
}
counters[val - 1] = counters[val - 1] + 1;
if (currentMaxCounter < counters[val - 1]) {
currentMaxCounter = counters[val - 1];
}
} else if (val === N + 1) {
maxApplied = true;
lastMaxCounter = currentMaxCounter;
}
}
// apply the lastMaxCounter to all counters
for (let k = 0; k < counters.length; k++) {
counters[k] = counters[k] < lastMaxCounter ? lastMaxCounter : counters[k];
}
return counters;
};
Here is C# solution give me 100% score
public int[] solution(int N, int[] A) {
int[] operation = new int[N];
int max = 0, globalMax = 0;
foreach (var item in A)
{
if (item > N)
{
globalMax = max;
}
else
{
if (operation[item - 1] < globalMax)
{
operation[item - 1] = globalMax;
}
operation[item - 1]++;
if (max < operation[item - 1])
{
max = operation[item - 1];
}
}
}
for (int i = 0; i < operation.Length; i++)
{
if (operation[i] < globalMax)
{
operation[i] = globalMax;
}
}
return operation;
}
Here is a pretty elegant soulution in Swift:
public func solution(_ N : Int, _ A : inout [Int]) -> [Int] {
var globalMax = 0
var currentMax = 0
var maximums: [Int: Int] = [:]
for x in A {
if x > N {
globalMax = currentMax
continue
}
let newValue = max(maximums[x] ?? globalMax, globalMax) + 1
currentMax = max(newValue, currentMax)
maximums[x] = newValue
}
var result: [Int] = []
for i in 1...N {
result.append(max(maximums[i] ?? globalMax, globalMax))
}
return result
}
Try this Java snippet. Its more readable and neater, you don't need to worry about bounds check and might evacuate your first findings related to the more efficient approach you have found, btw the max is on the main forloop not causing any overhead.
public final int[] solution(int N, int[] A)
{
int condition = N + 1;
int currentMax = 0;
int lastUpdate = 0;
int[] counters = new int[N];
for (int i = 0; i < A.length; i++)
{
int currentValue = A[i];
if (currentValue == condition)
{
lastUpdate = currentMax;
}
else
{
int position = currentValue - 1;
if (counters[position] < lastUpdate)
{
counters[position] = lastUpdate + 1;
}
else
{
counters[position]++;
}
if (counters[position] > currentMax)
{
currentMax = counters[position];
}
}
}
for (int i = 0; i < N; i++)
{
if (counters[i] < lastUpdate)
{
counters[i] = lastUpdate;
}
}
return counters;
}
Inspired by Andy's solution, here is a solution in Python that is O(N + M) and gets a score of 100. The key is to avoid the temptation of updating all the counters every time A[K] > 5. Instead you keep track of a global max and reset an individual counter to global max just before you have to increment it. At the end, you set the remaining un-incremented counters to global max. See the comments in the code below:
def solution(N,A):
max = 0
global_max = 0
counters = [0] * N
for operation in A:
if operation > N:
#don't update counters.
#Just keep track of global max until you have to increment one of the counters.
global_max = max
else:
#now update the target counter with global max
if global_max > counters[operation - 1]:
counters[operation - 1] = global_max
#increment the target counter
counters[operation - 1] += 1
#update max after having incremented the counter
if counters[operation - 1] > max:
max = counters[operation - 1]
for i in range(N):
#if any counter is smaller than global max, it means that it was never
#incremented after the global_max was reset. Its value can now be updated
#to global max.
if counters[i] < global_max:
counters[i] = global_max
return counters
Here's a C# solution that gave me 100% score.
The idea is to simply not update the max counters on the spot but rather do it when you actually get to that counter, and then even out any counters that were not set to the max in another loop.
class Solution
{
public int[] solution(int N, int[] A)
{
var result = new int[N];
var latestMax = 0;
var currentMax = 0;
for (int i = 0; i < A.Length; i++)
{
var currentValue = A[i];
if (currentValue >= 1 && currentValue <= N)
{
if (result[currentValue - 1] < currentMax)
{
result[currentValue - 1] = currentMax;
}
result[currentValue - 1]++;
if (result[currentValue - 1] > latestMax)
{
latestMax = result[currentValue - 1];
}
}
else if (currentValue == N + 1)
{
currentMax = latestMax;
}
}
for (int i = 0; i < result.Length; i++)
{
if (result[i] < currentMax)
{
result[i] = currentMax;
}
}
return result;
}
}

C#, one-dimension wrapping array

I have a one-dimensional array, and I need to run operations on it based on the adjacents cells of every cell.
For instance:
To run the operations on the first cell, I'll need to access the last cell and the second.
The second cell, I'll need to access the first cell and the third cell.
The last cell, I'll need to access the first cell and the one before the last cell.
My code so far is:
public static int[] firstRule(int[] numberArray)
{
for (int i = 0; i < numberArray.Length; i++)
{
if (numberArray[numberArray.Length - 1 - i] == numberArray[i] + 1
&& numberArray[i + 1] == numberArray[i] + 1)
{
numberArray[i] = numberArray[i] - 1;
}
}
return numberArray;
}
But the problem with my approach is that it would only work for the first cell, as it would take the last cell and the second cell correctly, but after that, everything would fall apart. I don't like posting without a lot of code but I have no clue how to follow this up.
I am trying to achieve the following:
Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.
Just keep it simple and use variables to calculate the left and right cell indices. Inside your for loop you can do this...
var leftCell = i - 1;
if (leftCell < 0)
{
leftCell = numberArray.Length - 1; // Wrap around to the end...
}
var rightCell = i + 1;
if (rightCell > numberArray.Length - 1)
{
rightCell = 0; // Wrap back around to the beginning...
}
// Now you can update your original code to use these computed indices...
if (numberArray[leftCell] == numberArray[i] + 1
&& numberArray[rightCell] == numberArray[i] + 1)
{
numberArray[i] = numberArray[i] - 1;
}
Try this out:
var len = numberArray.Length;
for (int i = 0; i < len; i++)
{
var leftIndex = (i - 1 + len) % len;
var rightIndex = (i + 1) % len;
// do your stuff with numberArray[leftIndex] and numberArray[rightIndex]
}
% is mod operator. % len allows you to stay in range 0..len-1, so you can walk through array as if it has become 'cyclic'
From your comments.
Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.
I would create a new array, populate it with the values of the existing array and then change the values of the new array according to the results of the value in the existing array.
Edit as Op is getting wrong values
I suspect you may not be copying the array correctly instead:
Existing Array array // The array you are passing in as parameter.
Declare a new empty array:
int[] newArray;
int size = array.length;
for(int i =1; i<size-1;i++){
if(array[i-1]==array[i+1])){
newArray[i]=array[i]+1;
}
else{
newArray[i]=array[i];
}
}
if(array[size-1]==array[0]){
newArray[size]= array[size]+1;
}
else{
newArray[i]=array[i];
}
if(array [size]==array[1]){
newArray[0]= array[0]+1;
}
else{
newArray[i]=array[i];
}
if there is a limit to the number and it reverts to zero after 2, then just do a simple if test for that.
int[] arr = new int[] { 1, 2, 3, 4, 5 };
var triples = arr.Select((n, i) =>
{
if (i == 0)
return Tuple.Create(arr[arr.Length - 1], arr[0], arr[1]);
else if (i == arr.Length - 1)
return Tuple.Create(arr[i - 1], arr[i], arr[0]);
else
return Tuple.Create(arr[i - 1], arr[i], arr[i + 1]);
});
foreach (var triple in triples)
{
Console.WriteLine(triple.Item1 + " " + triple.Item2 + " " + triple.Item3);
}
public static void firstRule(int[] numberArray)
{
for (int i = 0; i < numberArray.Length; i++)
{
int? prevElement = i == 0
? numberArray[numberArray.Length-1]
: numberArray[i - 1];
int? nextElement = i == numberArray.Length -1
? numberArray[0]
: numberArray[i + 1];
Console.WriteLine(
String.Format("Prev: {0}; Current: {1}; Next: {2}",
prevElement,
numberArray[i],
nextElement)
);
}
}
And then calling firstRule(new int[]{ 1, 2, 3 }); prints:
Prev: 3; Current: 1; Next: 2
Prev: 1; Current: 2; Next: 3
Prev: 2; Current: 3; Next: 1
OPTION 1
assign regardless
public static int[] firstRule(int[] numberArray)
{
int left,right;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
left = (i == 0) ? max : i - 1;
right = (i == max) ? 0 : i + 1;
numberArray[i] = (numberArray[left] == numberArray[right]) ? numberArray[i] + 1 : numberArray[i]; //always peforms an assignment;
}
return numberArray;
}
OPTION 2
conditionally assign
public static int[] secondRule(int[] numberArray)
{
int left,right;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
left = (i == 0) ? max : i - 1;
right = (i == max) ? 0 : i + 1;
if (numberArray[left] == numberArray[right])
{
numberArray[i]++;
}
}
return numberArray;
}
OPTION 3
left and right are only used 1 time in each iteration.. so why bother assigning them to a variable???...
public static int[] thirdRule(int[] numberArray)
{
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
if (numberArray[(i == 0) ? max : i - 1] == numberArray[(i == max) ? 0 : i + 1])
{
numberArray[i]++; // what happens if numberArray[i] is 3, should it become 4 or 0?
}
}
return numberArray;
}
OPTION 4 (UNSAFE)
unsafe - fixed - pointers
public static int[] fourthRule(int[] numberArray)
{
unsafe {
int* pointer, right, left;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
fixed (int* p1 = &numberArray[0], p2 = &numberArray[i], p3 = &numberArray[max])
{
pointer = p2;
if (i == 0)
{
left = p3;
right = pointer;
right++;
}
else if (i == max)
{
left = pointer;
left--;
right = p1;
}
else
{
left = pointer;
left--;
right = pointer;
right++;
}
if (*right == *left) {
*pointer = *pointer + 1;
}
}
}
}
return numberArray;
}
Recently came up against this myself and found this to be a solid method.
`
int length = numberArray.Length;
for (int i = 0; i < length; ++i)
{
int iMinus = (((i - 1) % length) + length) % length;
int iPlus = (((i + 1) % length) + length) % length;
}`
Something like this should work. It determines the appropriate cells for the operation in each loop and executes the operation. You didn't state what that operation was so you need to fill in the DoYourOperation method.
public static int[] processArray(int[] numberArray)
{
for (int i= 0; i < numberArray.Length; i++)
{
int firstCell;
int secondCell;
//Check if first cell
if(i == 0)
{
firstCell = numberArray[numberArray.length-1]; //Last cell
secondCell = numberArray[i++]; //Next cell
}
//Check if last cell
else if(i == numberArray.Length - 1)
{
firstCell = numberArray[i--]; //Cell before last one
secondCell = numberArray[0]; //First cell
}
else
{
firstCell = numberArray[i--];
secondCell = numberArray[i++];
}
DoYourOperation(firstCell, secondCell);
}
}

Smallest cost traversal of an array

How do you compute the smallest cost traversal of an integer array using steps and jumps, while also counting the first and last element of the array? A step is moving to the next immediate value in the array e.g. array[currentIndex + 1], and a jump is moving two spots e.g. array[currentIndex + 2]. I have the following function which I want to return the minimum sum started, it adds the first and last elements to the sum, but I'm stuck on the middle values of the array.
An example of this would be {2, 10, 4, 14, 44, 28, 16, 18} -> 66
which would add indexes 0, 2, 3, 5, and 7.
====
public int Cost(int[] board)
{
int sum = board[0];
int index = 0;
while (index < board.Length)
{
//Add the final array value to the sum
if (index + 1 == board.length)
{
sum += board[index];
break;
}
//Add other values here
index++;
}
return sum;
}
You can try this:
public int Cost(int[] board)
{
int[] cost = new int[board.Length];
for (int i = 0; i < board.Length; i++) {
if (i == 0) {
cost[i] = board[0];
} else if (i == 1) {
cost[i] = board[1] + cost[0];
} else {
cost[i] = board[i] + Math.Min(cost[i - 1], cost[i - 2]);
}
}
return cost[board.Length - 1];
}
One possible solution:
public int Cost(int[] board, int step = 1)
{
if (board == null) return -1;
if (board.Length == 0) return 0;
// always add first and last index (if its not the first)
int sum = board[0];
if (board.Length > 1) sum += board[board.Length - 1];
// assumes step is > 0
for (int i = step; i < (board.Length - 1); i += step)
{
sum += board[i];
}
return sum;
}
This allows for step to be a parameter. Maybe now you want to step either 1 or 2 away from the start. Maybe later you want to step 5 spots away.

Does adding extra loop at the end of n(log n) algorithm affect the complexity?

I wrote an algorithm to find length of longest increasing sequence in an array.
The algorithm has an array m which will contain the sequence but in some conditions, it doesn't contain the exact sequence. So in such case, I record the index and value which needs to be changed.
This algorithm is n(log n)
Now, to find the actual sequence, I loop through the array m and replace the value recorded in another array. Will my algorithm now still have the complexity if n(log n) ?
Below is the code in C#:
int[] b = { 1, 8, 5, 3, 7, 2, 9 };
int k = 1;
int i = 1;
int N = b.Length;
List<int> m = new List<int>();
int[] lup = new int[b.Length];
m.Add(0);
m.Add(b[0]);
lup[0] = 0;
while (i < N)
{
if (b[i] >= m[k])
{
k = k + 1;
m.Add(b[i]);
}
else
{
if (b[i] < m[1])
{
m[1] = b[i];
}
else
{
int j;
j = Binary_Search(m, b[i], m.Count - 1);
//if the item to be replaced was not the last element, record it
if (m[j] > b[i] && j != k)
{
lup[j] = m[j];
}
m[j] = b[i];
}
}
i = i + 1;
}
Console.WriteLine("The Input Sequence is : " + string.Join("\t", b));
Console.WriteLine("Length of Longest Up Sequence is : " + k.ToString());
List<int> result = new List<int>();
// create result based on m and lup
//DOES THIS LOOP EFFECT PERFORMANCE??
for(int x = 1; x < m.Count; x++)
{
if (lup[x] == 0)
{
result.Add(m[x]);
}
else
{
result.Add(lup[x]);
}
}
Your intuition is correct. Adding this loop is n*(log(n)+1) so it's still n*log(n).

Categories