How to find the count of the maximum pair of a window - algorithm

Today I got an interview question about finding the maximum pair window but I felt like I could solve it more efficient. I was wondering if theres any way to solve it more efficiently.
Input: nums = [1,3,-1,-3,5,3,6,7], k = 3, n = 7
Output: 3
Explanation:
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 4 (1,3) < 7 false
1 [3 -1 -3] 5 3 6 7 2 (3, -1) < 7 false
1 3 [-1 -3 5] 3 6 7 4 (5, -1) < 7 false
1 3 -1 [-3 5 3] 6 7 8 (5,3) > 7 true
1 3 -1 -3 [5 3 6] 7 11 (6,5) > 7 true
1 3 -1 -3 5 [3 6 7] 13 (6,7) > 7 true
just solved it by getting the subarray -> sorting then getting the last 2 element but I think theres a more efficient solution?

Related

Resetting an array of numbers by repeated subtraction from a sub-array

There is an array of numbers between 0 and 6 (base 7). For example {0 4 6 2 2 0 3 1}. Its maximum length can be 501 elements.
Each step we can subtract a number from any number of elements. All of the elements must be adjacent (form a continuous sub-array). The number subtracted from all of the elements must be the same.
If an element (let's call it A) after subtraction doesn't fit in the range of 0 to 6, then A becomes A modulo 7. For example after subtracting 3 from the whole array {0 4 6 2 2 0 3 1}, we would get
{4 1 3 6 6 4 0 5}.
The task is to find the smallest amount of steps necessary to get an array with just zeros.
For example for the array {0 4 6 2 2 0 3 1} it would take 4 steps:
{0 4 6 2 2 0 3 1} subtract 2 from elements with indexes 2-4
{0 4 4 0 0 0 3 1} subtract 4 from elements with indexes 1 and 2
{0 0 0 0 0 0 3 1} subtract 3 from the second to last element
{0 0 0 0 0 0 0 1} subtract 1 from the last element
{0 0 0 0 0 0 0 0}
First of all finding the solution using brute force is not possible, as for an array of 501 numbers
there are 126 505 506 possible first steps.
(6x(1x501 + 2x500 + 3x499 + 4x498 +...+ 501x1) = 6x21084251 = 126505506).
There would be a lot more possibilities if we include the steps following the first one.
I noticed we can remove an element if it has the same number next to it.
So the array {0 4 6 2 2 0 3 1} becomes {0 4 6 2 0 3 1}. This should simplify the problem.
I've tried dividing the array into sections using zeros as the dividers.
So for the array {0 4 6 2 0 3 1} we could consider two separate arrays: {4 6 2} and {3 1}.
I thought I could find the answers for those arrays and add them together for the final answer.
But I discovered arrays for which this approach doesn't work.
For example, for the array {3 2 1 0 1 2 3} this approach would yield the answer 3 + 3 = 6 while it should be 4 steps:
{3 2 1 0 1 2 3} subtract 3 from the whole array
{0 6 5 4 5 6 0}subtract 6 for indexes 1 to 5
{0 0 6 5 6 0 0} subtract 6 for indexes 2 to 4
{0 0 0 6 0 0 0} subtract 6 from the middle element
{0 0 0 0 0 0 0}
Another approach I tried was looking for pairs of the same number and dividing the array accordingly.
For example the array: {0 3 1 5 3 5 6 2 1 5 1}
would divide into three arrays {3 1 5 3} and {5 6 2 1 5} and {6}.
This would allow me to shorten a sub-array by two elements in just one step:
{3 1 5 3} {5 6 2 1 5} {6} subtract from the first subarray
{0 5 2 0} {5 6 2 1 5} {6} subtract from the second subarray
{0 5 2 0} {0 1 4 3 0} {6} remove zeroes on the sides -> {5 2} {1 4 3} {6}
But I couldn't find a final solution using this approach. Also I don't know how to check whether it always would return the best answer.

Sortperm for matrix sorting in Julia lang

I am using Julia 1.6.1.
B is a matrix. For example,
B =
[ 2 4 4 4 5 ;
1 2 2 3 5 ;
1 2 3 3 3 ;
1 2 2 5 6 ;
1 3 4 4 4 ; ]
I wanted to sort it forcsing on each row.
sortedB = sortslices( B, dims=1, rev=true)
Then, we get sorted B
sortedB =
[ 2 4 4 4 5 ; # 1st row of the original matrix B
1 3 4 4 4 ; # 5th row of the original matrix B
1 2 3 3 3 ; # 3rd row of the original matrix B
1 2 2 5 6 ; # 4th row of the original matrix B
1 2 2 3 5 ;] # 2nd row of the original matrix B
I would like to get the array [1 5 3 4 2].
How can I do that ?
It seems that sortperm does not work.
sortperm( sortslices( B, dims=1, rev=true) )
# ERROR: MethodError; no method matching sortperm(::Matrix{Int64})
If performance is an issue use a non-allocating version.
julia> sortperm(view.(Ref(B), 1:size(B,1), :), rev=true)
5-element Vector{Int64}:
1
5
3
4
2
Here are some benchmarks using BenchmarkTools:
julia> #btime sortperm(view.(Ref($B), 1:size($B,1), :),rev=true);
376.471 ns (3 allocations: 432 bytes)
julia> #btime sortperm(collect(eachslice($B,dims=1)),rev=true)
642.683 ns (6 allocations: 496 bytes);
you can use eachrow or eachslice:
julia> C = collect(eachslice(B,dims=1))
5-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
[2, 4, 4, 4, 5]
[1, 2, 2, 3, 5]
[1, 2, 3, 3, 3]
[1, 2, 2, 5, 6]
[1, 3, 4, 4, 4]
julia> sortperm(C,rev=true)
5-element Vector{Int64}:
1
5
3
4
2
although this will allocate more than necessary (collect is needed apparently)

How do I implement a nested for loop that converts every element in a 2D array into zeros in Clojure

I wish to implement (in Clojure) a nested for loop that converts every element in a 2D array into zero. Like the C code written below.
void set_to_zero(int n, int m[v][v]) {
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
m[i][j] = 0;
}
This is what I was able to do
(defn trial [n m]
(loop [i 0
j 0]
(if (= i (count (range n)))
(println m)
(if (= j (count (range n)))
(recur i j)
(assoc-in m[i j] 0)
)
)
)
)
This is what I get: i.e only one element changes and the rest stays same.
(trial 4 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
=> [[0 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
Update
(defn trial [n m]
(for [i (range n)
j (range n)]
(if (> i n)
m
(if-not (> j n)
;(recur (inc i) j)
(assoc-in m[i j] 0)
;(println i j)
)
)
)
)
New result
(trial 4 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
=>
([[0 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
[[9 0 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
[[9 8 0 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
[[9 8 2 0] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
[[9 8 2 3] [0 4 5 6] [6 1 8 9] [3 1 8 9]]
[[9 8 2 3] [8 0 5 6] [6 1 8 9] [3 1 8 9]]
[[9 8 2 3] [8 4 0 6] [6 1 8 9] [3 1 8 9]]
[[9 8 2 3] [8 4 5 0] [6 1 8 9] [3 1 8 9]]
[[9 8 2 3] [8 4 5 6] [0 1 8 9] [3 1 8 9]]
[[9 8 2 3] [8 4 5 6] [6 0 8 9] [3 1 8 9]]
[[9 8 2 3] [8 4 5 6] [6 1 0 9] [3 1 8 9]]
[[9 8 2 3] [8 4 5 6] [6 1 8 0] [3 1 8 9]]
[[9 8 2 3] [8 4 5 6] [6 1 8 9] [0 1 8 9]]
[[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 0 8 9]]
[[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 0 9]]
[[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 0]])
At the moment, it changes all the elements into 0 but does it separately would like it to return as one array with all the elements equal to zero.
P.S I am sure there are more efficient ways to achieve all zeros in a 2D vector but I'm particularly interested in the for loop method since it's popular in other languages and can help one more easily translate codes from other languages to Clojure (in some cases).
Thanks.
Since you already have the sizes of the structure (its a vector of
vectors) I think there is no need to pass in any sizes. So the one
thing to make sure is to keep the vectors (many tools in the clojure
belt use (lazy) sequences).
Using mapv does that. The function to map with can be (constantly
0). Then map that again over the outer vector. E.g.
Plain clojure:
(mapv (partial mapv (constantly 0)) [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
; → [[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]]
Alternative:
Using specter:
(setval [ALL ALL] 0 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
; → [[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]]
First, you're never increasing the values of i and j. So, they never change. Thus, you never get to the recur call.
They way you phrase your question gives the impression that you think, you edit the vector in-place. You don't. With every assoc-in you're creating a new vector. (A new associative data-structure to be more precise, but regardless.) A lot of copying will happen under the hoods.
My take on this is that you'd best create a fresh data-structure from the sizes of the existing one. If the nested vectors can be of differing sizes, the code #cfrick wrote (map ... constantly) is good. If all of the nested vectors have the same size, there's a simpler alternative. Try to find it and tell us how it goes. :-)
Clojure arrays are immutable, so if you want to operate in an imperative/mutable fashion you need to use an atom. Consider the following code:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn new-array
[M N]
(vec (for [i (range M)]
(vec (for [j (range N)]
(* i j))))))
(defn set-array-elem
[arr i j val]
(assoc-in arr [i j] val))
(defn change-array
[arr]
(let [work (atom arr)]
(doseq [i (range (count #work))]
(doseq [j (range (count (get #work i)))]
(swap! work set-array-elem i j
(* (inc i) (+ 3 j))))) ; set it to an "interesting" value
#work))
(dotest
(let [arr1 (new-array 3 5)]
(is= arr1
[[0 0 0 0 0]
[0 1 2 3 4]
[0 2 4 6 8]])
(is= (change-array arr1)
[[3 4 5 6 7]
[6 8 10 12 14]
[9 12 15 18 21]])))
Function set-array-elem returns a modified copy of the input array. The swap! in change-array calls this function and keeps the output in the atom work, replacing the previous immutable value. Thus we slowly transition from the original array to the final result, one element at at time.
I understand this is a learning exercise. If you ever need to manipulate arrays (nested vectors), please consider using either tupelo.array or tupelo.array.mutable and save a lot of writing (& debugging!)
Clojure template project to get you started. Includes many documentation links.
Tupelo Clojure library on Github
Tupelo Array
Tupelo Array Mutable
You can build a list of 0 with repeat:
(repeat 3 0)
; (0 0 0)
You can convert that into a vector with vec:
(vec (repeat 3 0))
; [0 0 0]
You just need to replace 3 with the length of each sub vectors:
(mapv #(-> (count %) (repeat 0) vec) [[1] [2 3] [4 5 6]])
; [[0] [0 0] [0 0 0]]
So if you know what the dimensions of your array are, create a new one.
(defn make-ary [m n]
(vec (repeat m (vec (repeat n 0)))))
I guess i was using assoc-in the wrong way. Was meant to use recur to implement assoc-in. I assume that was why I got several instances of the 2D vector returned instead of one. Using recur helped do that.
Thanks #cfrick #Stefan Kamphausen #Alan Thompson for pointing me to the right direction.
(defn trial [n m]
(loop [i 0
j 0
m m
]
(if (= i n)
m
(if (= j (dec n))
(recur (inc i) 0 (assoc-in m[i j] 0))
(recur i (inc j) (assoc-in m[i j] 0))
)
)
)
)
(trial 8 [[6 1 8 8 6 1 8 8][8 4 5 6 6 1 8 8][6 1 8 8 6 1 8 8][3 1 8 9 6 1 8 8][6 1 8 8 6 1 8 8][6 1 8 8 6 1 8 8][6 1 8 8 6 1 8 8][6 1 8 8 6 1 8 8]])
[[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]]

Confused about the depth-first-search result when using Golang

I tried to solve the 'Combination Sum' on leetcode, and the result is wrong when using test case:
[7,3,2] 18
I used C++ with the same logic and passed, but when using Golang, my result is:
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,7,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
and the correct one should be
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,2,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
the code is shown below:
import "sort"
func combinationSum(candidates []int, target int) [][]int {
result := make([][]int, 0, 0)
resultp := &result
sort.Ints(candidates)
helper(candidates, 0, target, make([]int, 0, 0), resultp, len(candidates))
return *resultp
}
func helper(nums []int, index int, target int, list []int, resultp *[][]int, length int) {
if target == 0 {
*resultp = append(*resultp, list)
return
}
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if (nums[i] > target) {
break
}
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
}
}
Can anyone tell me why the result is incorrect, I am just confused about the [2,2,2,2,2,7,3,3] in my answer, why the 7 is before the 3 since the array has been sorted? Or anyone can tell me what mistake I have made in my code
append function may or may not modify the underlying array that your slice refers to. So you are not creating a completely new list when using append. I changed helper to match your desired behavior.
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if nums[i] > target {
break
}
var newList []int
newList = append(newList, list...)
newList = append(newList, nums[i])
helper(nums, i, target - nums[i], newList, resultp, length)
}
If list has capacity, then it will be modified and therefore you are modifying your argument. Instead make a copy of list, and then append nums[i] to it.
See Go Slices: usage and internals
The line
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
may not perform as expected. It is called within the loop, and you are probably assuming that in the each iteration the append will always add the new member to the existing slice. If has more complex behavior that you seem not caring about enough:
If the new value fits into the current capacity of the backing array withing the slice, it is added to the current backing array. All variables assigned to that slice now report the updated content with the added new value present.
If the value does not fit, a new array is allocated. In this case further modifications of the returned slice will not change the content of the initial slice if that old value is also retained.
I am under impression that you may not expect value/content disagreement between the value returned by append and the parameter list you pass to it.
This behavior is described here (scroll to "gotcha").
So you can see the behavior a bit better by adding some print output:
https://play.golang.org/p/JPmqoAJE4S
Importantly, you can see it at this point:
0694 helper [2 3 7] 1 1 [2 2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
4425 calling down 1 6 [2 2 2 2 2 2] 3
8511 helper [2 3 7] 1 3 [2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
8511 calling down 1 3 [2 2 2 2 2 2 3] 3
8162 helper [2 3 7] 1 0 [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2]] 3
8162 solution [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3]]
1318 calling down 1 8 [2 2 2 2 2] 3
5089 helper [2 3 7] 1 5 [2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
5089 calling down 1 5 [2 2 2 2 2 3] 3
4728 helper [2 3 7] 1 2 [2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
1318 calling down 2 8 [2 2 2 2 2] 7
3274 helper [2 3 7] 2 1 [2 2 2 2 2 7] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 7 3 3]] 3
This is the sequence of actions:
You recursively call with [2 2 2 2 2 2 3] and append 3. You find that this is a valid solution and add [2 2 2 2 2 2 3 3] to the result slice.
You return up a few levels until you're back to [2 2 2 2 2] (before adding the 6th 2) and start trying to add 3s. You recursively call with [2 2 2 2 2] and append 3. Unfortunately, this overwrites your existing solution [2 2 2 2 2 2 3 3]. Since it's using the same backing array, you append 3 to the first 5 items in that slice, overwriting the 6th index in the slice you previously added to your solution set. Your second solution becomes [2 2 2 2 2 3 3 3] (note the 3 in the 6th slot)
You find that this solution set isn't going to work after a couple iterations (at [2 2 2 2 2 3 3]) because the remaining target (2) is less than the last number added (3), so you return up.
You repeat this sequence with a 7 in the 6th slot, overwriting the underlying array index again. Your second solution becomes [2 2 2 2 2 7 3 3], because you're still using the same underlying array. You find this solution also won't work, and return up.
After this point, you return up to before the list slice was greater than 4 in length (which is when the slice grew, by default it grows by doubling in size), meaning you're using a different (previous) backing array, which is why further iterations do not further change the existing solutions. By luck, none of the remaining solutions collide in a similar fashion.
This alternative print version shows you where the backing array changes (by showing where the address of the first entry changes): https://play.golang.org/p/nrgtMyqwow. As you can see, it changes when you grow beyond lengths 2, 4, and 8, but as you return upwards, you end up reverting back to different backing arrays.
The easiest solution to fix your specific problem is to copy the list slice before adding it to the solution set:
if target == 0 {
sol := make([]int, len(list))
copy(sol, list)
*resultp = append(*resultp, sol)
return
}
https://play.golang.org/p/3qTKoAumj0
[[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3] [2 2 2 2 3 7] [2 2 2 3 3 3 3] [2 2 7 7] [2 3 3 3 7] [3 3 3 3 3 3]]

convert multi D array into vector Matlab

Thanks in advance for the help
Suppose I have a multi D array such that
x(:,:,1) = [1 2 ; 3 4];
x(:,:,2) = [5 6 ; 7 8];
x(:,:,3) = [9 10 ; 11 12];
I would like quickly and efficiently convert x into
y = [1 5 9 2 6 10 3 7 11 4 8 12];
I there an efficient way to go about this besides using loops (the matrix I would like to do this to is relatively large)?
You can use the colon operator : but you first have to reorder the matrix x:
x(:,:,1) = [1 2 ; 3 4];
x(:,:,2) = [5 6 ; 7 8];
x(:,:,3) = [9 10 ; 11 12];
z=permute(x,[3 2 1]);
y=z(:).'

Resources