I'm working on the algorithm and it only gives an error in 1 case (Runtime Error) - swift

Only case 4 gives runtime error. I looked at other answers but couldn't find a solution
Question
I don't return the array. I'm just adding elements
func circularArrayRotation(a: [Int], k: Int, queries: [Int]) -> [Int] {
var result = [Int]()
for i in queries {
if i < k {
result.append(a[a.count-k+i])
}
else {
result.append(a[i-k])
}
}
return result
}
Isn't the time complexity of this algorithm O(n). Am I calculating wrong?

k can be much larger than the length of the array, so your approach is failing since the index is much larger than the array length.
To correctly handle this, make k equal to k modulus array_length, since rotating the array by array_length times effectively makes no changes to the current ordering.

Related

Does this sorting algorithm exist? (implemented in Swift)

This might be a bad question but I am curious.
I was following some data structures and algorithms courses online, and I came across algorithms such as selection sort, insertion sort, bubble sort, merge sort, quick sort, heap sort.. They almost never get close to O(n) when the array is reverse-sorted.
I was wondering one thing: why are we not using space in return of time?
When I organise something I pick up one, and put it where it belongs to. So I thought if we have an array of items, we could just put each value to the index with that value.
Here is my implementation in Swift 4:
let simpleArray = [5,8,3,2,1,9,4,7,0]
let maxSpace = 20
func spaceSort(array: [Int]) -> [Int] {
guard array.count > 1 else {
return array
}
var realResult = [Int]()
var result = Array<Int>(repeating: -1, count: maxSpace)
for i in 0..<array.count{
if(result[array[i]] != array[i]){
result[array[i]] = array[i]
}
}
for i in 0..<result.count{
if(result[i] != -1){
realResult.append(i)
}
}
return realResult
}
var spaceSorted = [Int]()
var execTime = BenchTimer.measureBlock {
spaceSorted = spaceSort(array: simpleArray)
}
print("Average execution time for simple array: \(execTime)")
print(spaceSorted)
Results I get:
Does this sorting algorithm exist already?
Is this a bad idea because it only takes unique values and loses the duplicates? Or could there be uses for it?
And why can't I use Int.max for the maxSpace?
Edit:
I get the error below
error: Execution was interrupted.
when I use let maxSpace = Int.max
MyPlayground(6961,0x7000024af000) malloc: Heap corruption detected,
free list is damaged at 0x600003b7ebc0
* Incorrect guard value: 0 MyPlayground(6961,0x7000024af000) malloc: * set a breakpoint in malloc_error_break to debug
Thanks for the answers
This is an extreme version of radix sort. Quoted from Wikipedia:
radix sort is a non-comparative sorting algorithm. It avoids comparison by creating and distributing elements into buckets according to their radix. For elements with more than one significant digit, this bucketing process is repeated for each digit, while preserving the ordering of the prior step, until all digits have been considered. For this reason, radix sort has also been called bucket sort and digital sort.
In this case you choose your radix as maxSpace, and so you don't have any "elements with more than one significant digit" (from quote above).
Now, if you would use a Hash Set data structure instead of an array, you would actually not need to really allocate the space for the whole range. You would still keep all the loop iterations though (from 0 to maxSpace), and it would check whether the hash set contains the value of i (the loop variable), and if so, output it.
This can only be an efficient algorithm if maxSpace has the same order of magnitude as the number of elements in your input array. Other sorting algorithms can sort with O(nlogn) time complexity, so for cases where maxSpace is much greater than nlogn, the algorithm is not that compelling.

I seem to have an infinite while loop in my Swift code and I can't figure out why

var array: [Int] = []
//Here I make an array to try to dictate when to perform an IBaction.
func random() -> Int {
let rand = arc4random_uniform(52)*10+10
return Int(rand)
}
//this function makes a random integer for me
func finalRand() -> Int {
var num = random()
while (array.contains(num) == true){
if (num == 520){
num = 10
}else {
num += 10
}
}
array.append(num)
return num
}
The logic in the while statement is somewhat confusing, but you could try this:
var array:Array<Int> = []
func finalRand() -> Int {
var num = Int(arc4random_uniform(52)*10+10)
while array.contains(num) {
num = Int(arc4random_uniform(52)*10+10)
}
array.append(num)
return num
}
This way there will never be a repeat, and you have less boiler code.
There is probably a better method involving Sets, but I'm sorry I do not know much about that.
A few things:
Once your array has all 52 values, an attempt to add the 53rd number will end up in an infinite loop because all 52 values are already in your array.
In contemporary Swift versions, you can simplify your random routine to
func random() -> Int {
return Int.random(in: 1...52) * 10
}
It seems like you might want a shuffled array of your 52 different values, which you can reduce to:
let array = Array(1...52).map { $0 * 10 }
.shuffled()
Just iterate through that shuffled array of values.
If you really need to continue generating numbers when you’re done going through all of the values, you could, for example, reshuffle the array and start from the beginning of the newly shuffled array.
As an aside, your routine will not generate truly random sequence. For example, let’s imagine that your code just happened to populate the values 10 through 500, with only 510 and 520 being the final possible remaining values: Your routine is 51 times as likely to generate 510 over 520 for the next value. You want to do a Fisher-Yates shuffle, like the built-in shuffled routine does, to generate a truly evenly distributed series of values. Just generate array of possible values and shuffle it.

Why O(n) takes longer than O(n^2)?

I have a LeetCode problem:
Given an M x N matrix, return True if and only if the matrix is Toeplitz.
A matrix is Toeplitz if every diagonal from top-left to bottom-right has the same element.
My solution is (Swift):
func isToeplitzMatrix(_ matrix: [[Int]]) -> Bool {
if matrix.count == 1 { return true }
for i in 0 ..< matrix.count - 1 {
if matrix[i].dropLast() != matrix[i + 1].dropFirst() { return false }
}
return true
}
As I understood Big O notation, my algorithm's time complexity is O(n), while LeetCode top answers' is O(n^2).
Top answers example:
func isToeplitzMatrix(_ matrix: [[Int]]) -> Bool {
for i in 0..<matrix.count-1 {
for j in 0..<matrix[0].count-1 {
if (matrix[i][j] != matrix[i+1][j+1]) {
return false;
}
}
}
return true;
}
Still, my algorithm takes 36ms (according to LeetCode), while top answer takes 28ms.
When I commented out if matrix.count == 1 { return true } it took even more time to run - 56ms.
Your time complexity for the function is also O(n^2) because the function call dropLast is O(n).
Edit:
Also mentioned by Rup and melpomene, the comparison of arrays also takes the complexity up to O(n^2).
Also, Big O notation describes how the algorithm scales in response to n, the number of data. It takes away any constants for brevity. Therefore, an algorithm with O(1) can be slower than an algorithm with O(n^3) if the input data is small enough.

Swift how does my function exceed O(n)?

I am trying to work on a leetcode problem that asks for
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
My solution to the problem is:
func findDisappearedNumbers(_ nums: [Int]) -> [Int] {
var returnedArray = [Int]()
if nums.isEmpty == false {
for i in 1...nums.count {
if nums.contains(i) == false {
returnedArray.append(i)
}
}
} else {
returnedArray = nums
}
return returnedArray
}
However, leetcode tells me that my solution is "Time limit exceeded"
Shouldn't my solution be O(n)? I am not sure where did I made it to be greater than O(n).
If I haven't missed anything your algorithm is O(n^2).
First, you iterate over each element of the array which is O(n), but for each element, you call contains which has to iterate over all the elements again and you end up with O(n^2).
I refrain from telling you the solution since it is for leetcode.

What is the O() complexity of this function?

This is a simple function that checks to see if the string is unique. I reason that the complexity should be N * N -> N^2. Is this correct? Even if the second N will always be smaller than the first.
func isUnique(_ str: String) -> Bool {
let charArr = Array(str.characters)
for (i1 , char) in charArr.enumerated() {
guard i1 != charArr.count - 1 else {
break
}
for (i2, char) in charArr[(i1 + 1)..<charArr.count].enumerated() {
if charArr[i1] == char {
return false
}
}
}
return true
}
Yes, There are a lot of myths behind this problem and when you analysis on Big O topic, you getting so many varying answers. And the most popular question is:
"If two nested for loops contains break statement. so still my complexity
is n*n or O(n2)?"
I think the simple answer is"
Big-O notation isn't about finding exact values given your actual parameters. It is about determining asymptotic runtime.