Related
I know how to generally manipulate and create a multidimensional array but I don't know all the utils and features that arrays have. I want to know is if I have a 2D array the size of [5][4], can I print it where the first line is in order, second is in reverse, and the third is in order... and so on.
For example:
[1 2 3 4] //in order
[8 7 6 5] //reverse
[9 10 11 12] //in order
[16 15 14 13] //reverse
[17 18 19 20] //in order
as my teacher stated "Define a two-dimensional array of size m × n. Write a method to initialize this array with numbers from 1 to m × n in the way as below: the first row, initialize the elements from left to right; the second row, initialize from right to left; then switch order. For example, if m=5; and n = 4; the array should be initialized to:"
I’m not sure if it should be done using a temp method or some other loop method.
You cannot reverse it directly. But you can have a loop and reverse the alternative rows:
void reverseArray() {
Integer[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
{17, 18, 19, 20}};
for (int i = 1; i < arr.length; i += 2) {
Collections.reverse(Arrays.asList(arr[i]));
}
}
if I have a 2D array the size of [5][4], can I print it where the
first line is in order, second is in reverse, and the third is in
order... and so on.
It's unclear how you want to use the output, but here is a literal way to do it:
public static void main(String[] args) {
int[][] values = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
for (int r = 0; r < values.length; r++) {
if (r % 2 == 0) {
// forwards
for (int c = 0; c < (values[r].length - 1); c++) {
System.out.print(values[r][c] + " ");
}
System.out.println(values[r][values[r].length - 1]);
} else {
// backwards
for (int c = (values[r].length - 1); c > 0; c--) {
System.out.print(values[r][c] + " ");
}
System.out.println(values[r][0]);
}
}
}
Output:
1 2 3 4
8 7 6 5
9 10 11 12
16 15 14 13
int[][] arr = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}};
AtomicInteger counter = new AtomicInteger(0);
Arrays.stream(arr).forEach(ints -> {
System.out.println(Arrays.stream(ints)
.mapToObj(String::valueOf)
.reduce((a, b) ->
counter.get() % 2 == 0 ? a + " " + b : b + " " + a).get());
counter.incrementAndGet();
});
This code uses the Stream API to iterate over an array. The first stream iterates over single-level arrays, the second - their elements, and then forms a string. Also, according to the counter value, items are combined from left to right or from right to left.
You can create such an array with a "snake order" without sorting at all, using a stream in a stream or a loop in a loop:
int m = 5;
int n = 4;
int[][] arr = IntStream
// create rows of array
.range(0, m).mapToObj(row -> IntStream
// for each row create cells where
// values are numbers from 1 to [m * n]
.range(0, n).map(cell -> {
int val = row * n;
if (row % 2 == 0)
// even rows:
// straight order
val += cell + 1;
else
// odd rows:
// reverse order
val += n - cell;
return val;
})
// return int[] array
.toArray())
// return int[][] 2d array
.toArray(int[][]::new);
int m = 5;
int n = 4;
int[][] arr = new int[m][n];
// create rows of array
for (int row = 0; row < m; row++) {
// for each row create cells where
// values are numbers from 1 to [m * n]
for (int cell = 0; cell < n; cell++) {
int val = row * n;
if (row % 2 == 0)
// even rows:
// straight order
val += cell + 1;
else
// odd rows:
// reverse order
val += n - cell;
arr[row][cell] = val;
}
}
Arrays.stream(arr).map(Arrays::toString).forEach(System.out::println);
// [1, 2, 3, 4]
// [8, 7, 6, 5]
// [9, 10, 11, 12]
// [16, 15, 14, 13]
// [17, 18, 19, 20]
See also:
• How do I rotate a matrix 90 degrees counterclockwise in java?
• Is there any other way to remove all whitespaces in a string?
Not as efficient as nested loops, one can simply iterator from 1 to 20 and determine row i and column j.
final int M = 5;
final int N = 4;
int[][] matrix = new int[M][N];
IntStream.range(0, M*N)
.forEach(no -> { // no = 0, 1, 2, ... , M*N-1
int i = no / N; // Row.
int j = no % N; // Increasing column (for even row).
if (i % 2 == 1) { // Odd row.
j = N - 1 - j; // Decreasing column.
}
matrix[i][j] = no + 1;
});
i % 2 is the modulo 2, rest by division of 2, hence 0 for even, 1 for odd.
Or use a bit more language features:
IntStream.range(0, N)
.forEach(i -> {
int no = N * i;
IntUnaryOperator jToValue = i % 2 == 0
? j -> no + 1 + j
: j -> no + N - 1 -j;
Arrays.setAll(matrix[i], jToValue);
});
Here Arrays.setAll(int[], (int index) -> int) fills the array based on the index.
About the question of there being some nice function:
You probably saw List.reverse; there does not exist an Arrays.reverse, hence Arrays.setAll seems to be best. In this case where the values are increasing one theoretically could also sort all odd rows reversed. But only with a trick, and sorting costs.
It is interesting that there are so many solutions. Instead of waggling the dog's tail one can take the tail and waggle the dog.
Given two arrays of ints, a and b, try to create an arithmetic sequence by adding ints from b into a. Return the maximum length of a or -1 if there does not exist an arithmetic sequence e.g. a = [2, 4, 8], b = [1, 6, 10, 12] -> a = [2, 4, 6, 8, 10, 12] -> return 6
I tried creating a new array and merging both a and b and counting the longest subsequence but the count could remove elements from a which should not be touched
static int maxSeq(int[] arr1, int[] arr2){
if(arr1.length ==0)return 0;
int n =arr1.length, m = arr2.length;
int[] arr = new int[n+m];
System.arraycopy(arr1,0,arr,0,n);
System.arraycopy(arr2,0,arr,n,m);
Arrays.sort(arr);
int result =0;
Map<Integer,Integer>[]d = new HashMap[n+m];
for(int i =0; i < arr.length;i++){
d[i] = new HashMap<Integer, Integer>();
}
for(int i =1; i < arr.length; ++i){
for(int j = 0; j<i;++j ){
int diff = arr[i]-arr[j];
int len =2;
if(d[j].containsKey(diff)){
len = d[j].get(diff) +1;
}
d[i].put(diff,len);
result = Math.max(result,d[i].get(diff));
}
}
return result;
}
a = [2, 4, 8], b = [1, 6, 10, 12] -> a = [2, 4, 6, 8, 10, 12] -> return 6
int[] a = {5,7,13,14}, b = {9,11,15}; return -1 not 6
I think you should try to fix your code.
if(d[j].containsKey(diff)){ len = d[j].get(diff) +1; }
Here you are looking for differences in a map of some index j, and there should be only one map of key value paires, not array of maps.
The key here is to fill in array A with numbers from array B so A become an arithmetic sequence.
Solution:
First find the minimum gap between 2 consequence number in A
With the given "gap", try to see if an arithmetic sequence can be build by looping through the 2 arrays, and find out if numbers in B can fill in array A so A become arithmetic with step = "gap". Take count of the length if success.
If it can be found, try to see if smaller gap can build longer arithmetic sequence by looping through all the divisor of the original "gap" as the new "gap" and test again. (example: A = [ 1,5], B= [3,7,9] => Previous step see that we can build arithmetic sequence [1,5,9], but the final answer should be [1,3,5,7,9].
I'd like to share my solution (probably is not optimized and I did not wrote many tests, but it worked on your two sample tests):
Idea:
Notice the common difference d of arithmetic sequence is upperbounded by min(a[i] - a[i-1]), otherwise we won't be able to visit all elements in a
We iterate on common difference d to check the length of each potential list, and find the max length
Complete code in Python:
(Suppose a, b are both sorted)
def max_arithmetic_length(a, b):
min_diff = float('inf') # common difference d is upper bounded by min_diff
for i in range(1, len(a)):
min_diff = min(min_diff, a[i] - a[i-1])
d_a = {x : True for x in a}
d_b = {x : True for x in b}
max_cnt = 0
for d in range(1, min_diff + 1):
skip_current_d = False # a switch to skip outer loop
for x in a:
if (x - a[0]) % d != 0: # must exist: a[i] - a[0] = kd
skip_current_d = True
break
if skip_current_d:
continue
cur = a[0]
cnt = 0
visited = {}
while cur in d_a or cur in d_b:
cnt += 1
visited[cur] = True
cur += d
if a[-1] not in visited: # if the last element in a is visited, then every element in a is visited
continue
# check those smaller than a[0] (may only exist in b)
cur = a[0] - d
while cur in b:
cnt += 1
cur -= d
max_cnt = max(cnt, max_cnt)
return max_cnt if max_cnt else -1
a = [2, 4, 8]
b = [1, 6, 10, 12]
print(max_arithmetic_length(a,b)) # return 6
a = [5,7,13,14]
b = [9,11,15]
print(max_arithmetic_length(a,b)) # return -1
I am trying to solve:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
Here is my solution:
def twoSum(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
hash_table = {}
k = target
for i, x in enumerate(nums):
if x not in hash_table:
hash_table[x] = i
for x in nums:
if k-x in hash_table:
if hash_table[k-x]!= hash_table[x]:
return [hash_table[x], hash_table[k-x]]
Now the solution is not correct as it fails the test case like [3,3], 6. Now both 3s get stored in hash table as one entry which is expected, so only one index is recorded in the hash table for 3 and my solution doesn't work.
So, I think the solution might not be with hash tables. But the correct solution is:
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
Now, this is essentially the same solution in Java and it is mentioned as the correct one.
So, my question is:
How can I change my solution in Python to work and not fail the test case?
How is the Java solution different, does its hash table have some other behavior?
Thanks for your help.
The Java solution has a check that takes care of two equal elements:
if (map.containsKey(complement) && map.get(complement) != i)
The first part of this condition - map.containsKey(complement) - means that the number complement is present in the Map, while the second part - map.get(complement) != i) - means that the index of complement stored in the map is different from the index i. This means that if complement == nums[i], there are two identical numbers in the input array.
I don't know Python, but it looks like your code fails because
if hash_table[k-x]!= hash_table[x]
always returns false when k-x == x. You need to compare hash_table[k-x] to the current index of the input array.
Based on your first Python loop, I'm assuming the second loop should look like this:
for i, x in enumerate(nums):
if k-x in hash_table:
if hash_table[k-x]!= i:
return [i, hash_table[k-x]]
Why not go with something simple as:
def twoSum(nums, target):
for i, num1 in enumerate(nums):
for j, num2 in enumerate(nums):
if num1 + num2 == target and i != j:
return [i, j]
return [-1, -1] # or whaterver you want to say "no solution found"
this produces:
print twoSum([2, 7, 11, 15], 9) # =>[0, 1] 2+7
print twoSum([2, 7, 11, 15], 22) # =>[1, 3] 7+15
print twoSum([2, 7, 11, 15], 23) # => [-1, -1] no solution
Alternatively to the hash table solution, you can
sort the array (time O(N Log N)),
maintain two indexes i, j such that num[i] + num[j] <= sum < num[i] + num[j+1]; every time you increase i, you decrease j by 0 or more to adjust. i starts from 0 and j from the end.
At worse you increase i N times and decrease j N times for a total of O(N) operations. In case of equality, you are done.
This can be done in-place.
Tried out using the JavaScript,
let qarr = [2, 3, 5, 6, 7, 9, 21, 24, 27, 35, 50, 98] //sorted Array
const qk = 85
function check_sum(arr, k){
for( i in arr){
if(arr[i]+arr[arr.length-1] === k){
return [qarr.indexOf(arr[i]), qarr.indexOf(arr[arr.length-1])]
}
else{
if(arr[i]+arr[arr.length-1] >= k){
if(arr.length == 2){
return arr[0]+arr[1] == k ? [qarr.indexOf(arr[0], qarr.indexOf(arr[1]))] : [null, null]
}
else if(arr.length == 1){
return arr[0]*2 == k ? [qarr.indexOf(arr[0]), qarr.indexOf(arr[0])] : [null, null]
}
else{
return check_sum(arr.slice(i), k)
}
}
}
}
}
res = check_sum(qarr.filter(a=> a<=qk), qk)
console.log('result', res)
I'm looking for a hint on how to solve this or where I am going wrong.
The question is as follows: Write a static method named stretch that accepts an array of integers as a parameter and returns a new array twice as large as the original, replacing every integer from the original array with a pair of integers, each half the original. If a number in the original array is odd, then the first number in the new pair should be one higher than the second so that the sum equals the original number. For example, if a variable named list refers to an array storing the values {18, 7, 4, 24, 11}, the call of stretch(list) should return a new array containing {9, 9, 4, 3, 2, 2, 12, 12, 6, 5}. (The number 18 is stretched into the pair 9, 9, the number 7 is stretched into 4, 3, the number 4 is stretched into 2, 2, the number 24 is stretched into 12, 12 and the number 11 is stretched into 6, 5.)
Test your code with the following class:
import java.util.*;
public class TestStretch {
public static void main(String[] args) {
int[] list = {18, 7, 4, 14, 11};
int[] list2 = stretch(list);
System.out.println(Arrays.toString(list)); // [18, 7, 4, 24, 11]
System.out.println(Arrays.toString(list2)); // [9, 9, 4, 3, 2, 2, 7, 7, 6, 5]
}
// your code goes here
}
This is currently what I have, but it is not quite working correctly... I have a feeling it is how i'm using int i and int j, but i'm not sure what to do to fix it so that it works as intended.
import java.util.*;
public class TestStretch {
public static void main(String[] args) {
int[] list = {18, 7, 4, 14, 11};
int[] list2 = stretch(list);
System.out.println(Arrays.toString(list)); // [18, 7, 4, 24, 11]
System.out.println(Arrays.toString(list2)); // [9, 9, 4, 3, 2, 2, 7, 7, 6, 5]
}
public static int[] stretch(int[] array){
int length = array.length;
int[] newArray = new int[array.length*2];
for(int i = 0; i< length; i=i+2){
int j = 0;
if(array[i] % 2 == 0){
newArray[i] = (array[j]/2);
newArray[i+1] = newArray[i];
j++;
} else{
newArray[i] = (array[j]/2);
newArray[i+1] = (newArray[i] + 1);
j++;
}
}
return newArray;
}
}
The output I get is:
[18, 7, 4, 14, 11]
[9, 9, 9, 9, 9, 10, 0, 0, 0, 0]
Instead of:
[18, 7, 4, 24, 11]
[9, 9, 4, 3, 2, 2, 7, 7, 6, 5]
There are a couple of mistakes:
The loop iterates only until half of the array, skipping elements by 2
The value of j is reset to 0 in each iteration
Also, the algorithm can be simplified:
For each index i in the input, you want to set in the destination at position 2 * i and 2 * i + 1.
The second value to set is simply the original value divided by 2, with integer truncation
The first value to set is the same as the second, +1 if the division by 2 leaves a remainder
With the above issues corrected, and the implementation simplified:
int[] newArray = new int[array.length * 2];
for (int i = 0; i < array.length; i++) {
newArray[2 * i] = array[i] / 2 + array[i] % 2;
newArray[2 * i + 1] = array[i] / 2;
}
return newArray;
First of all, if you are looping to the old array's length, don't increment i by 2.
If i increases by 1 each time, we need to figure out how to map the old array's index i to the new array's index. It is quite simple: the new array's indices are just i*2 and i*2+1.
Now j seems redundant because it always holds the same value as i, so you can remove that.
This is the full code:
int length = array.length;
int[] newArray = new int[array.length*2];
for(int i = 0; i< length; i++){
if(array[i] % 2 == 0){
newArray[i*2] = (array[i]/2);
newArray[i*2+1] = newArray[i*2];
} else{
newArray[i*2] = (array[i]/2);
newArray[i*2+1] = (newArray[i*2] + 1);
}
}
return newArray;
Three mistakes:
j should be initialized outside the for-loop
we should use j to record the new value into the new array
we should increment j upon every iteration in 2 - and we should increment i only by 1 (since we're using j to insert two item while we use i to iterate the original array):
int j = 0;
for(int i = 0; i< length; i++){
if(array[i] % 2 == 0){
newArray[j] = newArray[j+1] = array[i]/2;
} else{
newArray[j] = array[i]/2 + 1;
newArray[j+1] = array[i]/2;
}
j += 2;
}
Note: giving a variable that holds an array the name "list" might create confusion!
for(int i = 0; i< length; i=i+2){
length is the length of the original array, so you iterate only over half of the values because you increase i by 2 each step.
if(array[i] % 2 == 0){
This should be
if(array[j] % 2 == 0){
And because you define j within your for-loop, array[j] always returns 18. Oh and you set the second element of the tuple to be the higher one while your comment in the code says the contrary should take place.
So a fixed version of your method would look like this:
public static int[] stretch(int[] array){
int length = array.length;
int[] newArray = new int[array.length*2];
int j = 0;
for(int i = 0; i< newArray.length; i=i+2){
if(array[j] % 2 == 0){
newArray[i] = (array[j]/2);
newArray[i+1] = newArray[i];
} else{
newArray[i+1] = (array[j]/2);
newArray[i] = (newArray[i+1] + 1);
}
j++;
}
return newArray;
}
Avoiding duplicate code:
public static int[] stretch(int[] array){
int[] newArray = new int[array.length*2];
int j = 0;
for(int i = 0; i< newArray.length; i=i+2){
int val = array[j];
newArray[i] = (val/2);
newArray[i+1] = newArray[i];
if(val % 2 != 0){
newArray[i]++;
}
j++;
}
return newArray;
}
Or using fancy streams:
public static int[] stretch(int[] array){
return Arrays.stream(array)
.flatMap(elem -> {
int half = elem / 2;
int otherHalf = half;
if (elem % 2 != 0) {
half++;
}
return IntStream.of(half, otherHalf);
}).toArray();
}
}
I need the output of permutation for bits of length 3 to be (the order doesn't matter as the initial combination of 0 and 1 is generated randomly):
[0,0,0]
[0,0,1]
[0,1,0]
[0,1,1]
[1,0,0]
[1,0,1]
[1,1,0]
[1,1,1]
I have done but it seems that there are duplicates and some possible permutation are not being displayed which I'm not sure why. This is my code:
'
ArrayList<Item> itemsAvailable = new ArrayList<Item>();
ArrayList<Integer>bits = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> tried = new ArrayList<ArrayList<Integer>>();
itemsAvailable.add(new Item(5,4));
itemsAvailable.add(new Item(12,10));
itemsAvailable.add(new Item(8,5));
System.out.println("itemsAvailable: " + itemsAvailable);
Random r = new Random();
//permutations
for(int i = 0; i < Math.pow(2,itemsAvailable.size()); i++){
//Generate random bits
for(int j = 0; j < itemsAvailable.size(); j++){
int x = 0;
if (r.nextBoolean())
x = 1;
bits.add(x);
}
System.out.println("Added to bits #" + (i+1) + ": " + bits);
bits = new ArrayList<Integer>();
}
'
The output that I obtained is:
Added to bits #1: [0, 0, 1]
Added to bits #2: [1, 1, 0] - duplicate
Added to bits #3: [1, 0, 1]
Added to bits #4: [0, 0, 1]
Added to bits #5: [0, 0, 0] - dupicate
Added to bits #6: [1, 1, 0] - dupicate
Added to bits #7: [1, 1, 1]
Added to bits #8: [0, 0, 0] - dupicate
Therefore how can I obtain 8 different permutations as the bits are generated randomly? Please help.
Thank you.
There's an easier way to go about this. Think of what these bits represent in binary, in unsigned two's complement:
[0,0,0] -> 0
[0,0,1] -> 1
[0,1,0] -> 2
...
[1,1,1] -> 7
So the easy way to get all these permutations is:
for (int i = 0; i < 8; ++i) {
bits.add(i);
}
Where does that 8 come from? It's just 2^3, since you wanted length 3.
This technique works for up to 31 bits, since Java's int type is signed (whereas the above basically treats it as unsigned, which works at those lower numbers).
You can bump it up to 2^63 by using long instead of int, and you can get 64-length by just enumerating all longs. Beyond that, you'll need a different approach; but 2^64 longs, at 8 bytes per long, is about 1.5e11 gigabytes -- so you'll have run out of RAM way before you need a more complex algorithm.
If you are aware that the combinations is nothing else than counting then you can just do something like:
public static void main(String[] args) {
for (int i = 0; i < 8; i++) {
System.out.println(String.format("%3s", Integer.toBinaryString(i)).replace(' ', '0'));
}
}
where
Integer.toBinaryString(i) will print the i value as binary
and
String.format("%3s", Integer.toBinaryString(i)).replace(' ', '0')
will add leading zeros to the left so you can read it better