Swift Maximum Consecutive Positive Numbers

swift maximum consecutive positive numbers

Update: Simpler solution: Split the array into slices of
positive elements, and determine the maximal slice length:

let  numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
let maxConsecutive = numbers.split(whereSeparator: { $0 <= 0 }).map { $0.count }.max()!
print(maxConsecutive) // 3

Old answer:) Using the ideas from Swift running sum:

let  numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]

let maxConsecutive = numbers.map({
() -> (Int) -> Int in var c = 0; return { c = $0 > 0 ? c + 1 : 0; return c }
}()).max()!

Here map() maps each array element to the count of consecutive positive
numbers up to the elements position, in this case

[1, 2, 3, 0, 0, 1, 2, 0, 0, 0, 1]

The transformation is created as an "immediately evaluated
closure" to capture a variable c which holds the current number of
consecutive positive numbers. The transformation increments or resets c,
and returns the updated value.

If the array is possibly large then change it to

let maxConsecutive = numbers.lazy.map( ... ).max()!

so that the maximum run length is determined without creating an
intermediate array.

maximum number of consecutive in swift

Your question is more appropriate for the Code Review site. The rankings in LeetCode are not reliable and may vary from submission to the next (with the same code).

Here is a solution that avoids if .. else (original java code here) :

func findMaxConsecutiveOnes4(_ nums: [Int]) -> Int {
var globalMax = 0
var localMax = 0

for num in nums {
localMax *= num
localMax += num
globalMax = max(globalMax, localMax)
}
return globalMax
}

For benchmarking, I've used the following code :

let array = (0...10_000).map { _ in Int.random(in: 0..<2) }

let start1 = mach_absolute_time()
let x1 = findMaxConsecutiveOnes1(array)
let end1 = mach_absolute_time()
print("1st", x1, Double(end1 - start1)/Double(1e3), "us")

let start2 = mach_absolute_time()
let x2 = findMaxConsecutiveOnes2(array)
let end2 = mach_absolute_time()
print("2nd", x2, Double(end2 - start2)/Double(1e3), "us")

let start3 = mach_absolute_time()
let x3 = findMaxConsecutiveOnes3(array)
let end3 = mach_absolute_time()
print("3rd", x3, Double(end3 - start3)/Double(1e3), "us")

Where findMaxConsecutiveOnes is your solution, findMaxConsecutiveOnes2 is Joakim's, and findMaxConsecutiveOnes3 is the one proposed in this answer.

Compiled with optimizations (-O) in the terminal, here are the execution times:

  • findMaxConsecutiveOnes1 : 49.079 us
  • findMaxConsecutiveOnes2 : 54.016 us
  • findMaxConsecutiveOnes3 : 14.883 us

Faster than 100.00% of Swift online submissions (For now)

312

The following implementation is considered the current fastest by LeetCode :

func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {

guard !nums.isEmpty else {
return 0
}

var globalMax = 0
var localMax = -1

for i in 0..<nums.count {
if nums[i] != 1 { //It is faster than: if nums[i] == 0
localMax = i
}
globalMax = max(globalMax, i - localMax)
}
return globalMax
}

Here is the original C++ implementation.

In my benchmarks, it didn't perform as expected : 33.615 us on a 10,000 element array.

But, on smaller sized arrays, it proved to be the quickest solution.


Even faster solution

308

This is the fastest :

func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {

guard !nums.isEmpty else {
return 0
}

var globalMax = 0
var lastZeroIdx = -1

for i in 0..<nums.count {
if nums[i] == 0 {
globalMax = max(lastZeroIdx == -1 ? i : i - lastZeroIdx - 1, globalMax)
lastZeroIdx = i
}
}
globalMax = max(lastZeroIdx == -1 ? nums.count : nums.count - lastZeroIdx - 1, globalMax)
return globalMax
}

It was ported from this java implementation.

In my benchmarks, I couldn't notice any improvement in execution time on neither small (10-element) nor big (10,000-element -> 42.363 us) arrays .

swift: average consecutive positive number

A possible solution: Split the array into slices of consecutive
positive numbers, then compute the average slice length:

let numbers = [-1.0, 1.0, 3.0, 4.0, -1.0, -2.0, 2.0]

let slices = numbers.split(whereSeparator: { $0 <= 0 })
// --> [ArraySlice([1.0, 3.0, 4.0]), ArraySlice([2.0])]

let avg = Double(slices.reduce(0, { $0 + $1.count })) / Double(slices.count)
print(avg) // 2.0

Best way to find the largest amount of consecutive integers in a sorted array in swift, preferably not using a for loop

You can do it like this:

let array = [1, 3, 4, 7, 8, 9, 12, 14, 15]  
if let maxCount = IndexSet(array).rangeView.max(by: {$0.count < $1.count})?.count {
print("The largest amount of consecutive integers: \(maxCount)")
//prints 3
}

Best way to loop through array and group consecutive numbers in another array SWIFT 4?

My suggestion is IndexSet where consecutive items are stored as ranges.

  • Create the index set from the array.
  • Get the rangeView.
  • Map the ranges to arrays.

let myNumbersArray = [1,2,3,4,10,11,15,20,21,22,23]
let indexSet = IndexSet(myNumbersArray)
let rangeView = indexSet.rangeView
let newNumbersArray = rangeView.map { Array($0.indices) }

Swift running sum

The general combinator you're looking for is often called scan, and can be defined (like all higher-order functions on lists) in terms of reduce:

extension Array {
func scan<T>(initial: T, _ f: (T, Element) -> T) -> [T] {
return self.reduce([initial], combine: { (listSoFar: [T], next: Element) -> [T] in
// because we seeded it with a non-empty
// list, it's easy to prove inductively
// that this unwrapping can't fail
let lastElement = listSoFar.last!
return listSoFar + [f(lastElement, next)]
})
}
}

(But I would suggest that that's not a very good implementation.)

This is a very useful general function, and it's a shame that it's not included in the standard library.

You can then generate your cumulative sum by specializing the starting value and operation:

let cumSum = els.scan(0, +)

And you can omit the zero-length case rather simply:

let cumSumTail = els.scan(0, +).dropFirst()

Keeping track of the longest streak in swift

I have tried this and you can store all the streak values in an array and then find the maximum value out of it. Below is the code.

var streak = 0
var streakArr = [Int]()

// This will generate the random values

func randomBool() -> Bool {

return arc4random_uniform(2) == 0
}

for i in 0...10 {

let obj = randomBool()

if !obj {

streak += 1

} else {

streak = 0

}

streakArr.append(streak)
}

streakArr // OP- [1, 0, 1, 2, 0, 0, 0, 0, 1, 2, 3]
streakArr.max() // will give you the maximum value ie. 3

maximum sum of n consecutive elements of array

here is my idea: traverse the array from 0 to (array length - N), and determine the sum of next N-item by using the following expression:

sum of next N-item = previous sum - first item in previous sub-array + last item in next sub-array

Example:

Array = {2,5,3,4,6}

when i = 0, sum = (2 + 5) = 7, max sum = 7

when i = 1, sum = 7 - 2 + 3 = 8, since 8 > 7, so max sum = 8

when i = 2, sum = 8 - 5 + 4 = 7, since 7

when i = 3, sum = 7 - 3 + 6 = 10, since 10 > 8, so max sum = 10

below is the sample code in c#

static int GetLargestSum(int[] array, int n)
{
int largestSum = 0;
int previousSum = 0;

for (int i = 0; i <= array.Length - n; i++)
{
if (i == 0)
{
for (int j = 0; j < n; j++)
{
largestSum += array[j];
}

previousSum = largestSum;
}
else
{
int currentSum = previousSum - array[i - 1] + array[i + n - 1];
if (currentSum > largestSum)
{
largestSum = currentSum;
}
previousSum = currentSum;
}
}

return largestSum;
}

Given a number N, find the number of ways to write it as a sum of two or more consecutive integers

We can use dynamic programming to calculate the sums of 1+2+3+...+K for all K up to N. sum[i] below represents the sum 1+2+3+...+i.

sum = [0]
for i in 1..N:
append sum[i-1] + i to sum

With these sums we can quickly find all sequences of consecutive integers summing to N. The sum i+(i+1)+(i+2)+...j is equal to sum[j] - sum[i] + 1. If the sum is less than N, we increment j. If the sum is greater than N, we increment i. If the sum is equal to N, we increment our counter and both i and j.

i = 0
j = 0
count = 0
while j <= N:
cur_sum = sum[j] - sum[i] + 1
if cur_sum == N:
count++
if cur_sum <= N:
j++
if cur_sum >= N:
i++

There are better alternatives than using this dynamic programming solution though. The sum array can be calculated mathematically using the formula k(k+1)/2, so we could calculate it on-the-fly without need for the additional storage. Even better though, since we only ever shift the end-points of the sum we're working with by at most 1 in each iteration, we can calculate it even more efficiently on the fly by adding/subtracting the added/removed values.

i = 0
j = 0
sum = 0
count = 0
while j <= N:
cur_sum = sum[j] - sum[i] + 1
if cur_sum == N:
count++
if cur_sum <= N:
j++
sum += j
if cur_sum >= N:
sum -= i
i++


Related Topics



Leave a reply



Submit