I have this program where the number of elements of the array "n" is entered and then the target is entered "d",
Then I want to add two numbers from the matrix and the addition is equal to target "d",
Then I want to return an array of Indexes of these two numbers
Example:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
I wrote this program, but I could not return the Indexes,
How can I solve the problem?
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
System.out.println("This the number that we want it" + "\n" + i + "\n" + j);
}
}
}
return nums;
}
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
res[0] = i;
res[1] = j;
System.out.println("This the number that we want it" + "\n" + i + "\n" + j);
}
}
}
return res;
}
You need to create a new array of size 2 and return that.
If you are happy with O(n^2) complexity, you don't need to read ahead. But here is a solution with O(n) time complexity:
public int[] twoSum(int[] numbers, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < numbers.length; map.put(numbers[i], ++i)) {
if (map.containsKey(target - numbers[i])) {
return new int[] {map.get(target - numbers[i]), i + 1};
}
}
return new int[]{0,0};
}
Look at this solutions!
Time complexity O(n^2), space complexity O(1)
public static int[] foo(int[] arr, int d) {
for (int i = 0; i < arr.length - 1; i++)
for (int j = i + 1; j < arr.length; j++)
if (arr[i] + arr[j] == d)
return new int[] { i, j };
return new int[] {-1, -1};
}
Time complexity O(n), space complexity O(n)
public static int[] foo(int[] arr, int d) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(d - arr[i]))
return new int[] { map.get(d - arr[i]), i };
map.put(arr[i], i);
}
return new int[] {-1, -1};
}
Related
Leetcode #167 is almost same as #1, but why I cannot only add a if condition?
Q: Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
Note:
Your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
The sum of 2 and 7 is 9.
Therefore index1 = 1, index2 = 2.
My code:
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 1; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[j] == target - numbers[i]) {
if(numbers[i] < numbers[j])
return new int[] { i, j };
}
}
}
return null;
}
}
Why I always return null? where is my mistake? How to fix it?
Because the question says array starts from 1 does not mean array starts from 1 in java.If you want to return i,j as non-zero you should go from 1 to length+1 and then inside the conditions you should check indexes as i-1,j-1 or just start from 0 and return i+1,j+1.
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 1; i < numbers.length+1; i++) {
for (int j = i + 1; j < numbers.length+1; j++) {
if (numbers[j-1] == target - numbers[i-1]) {
if(numbers[i-1] < numbers[j-1])
return new int[] { i, j };
}
}
}
return null;
}
}
or you can do,
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[j] == target - numbers[i]) {
if(numbers[i] < numbers[j])
return new int[] { i+1, j+1 };
}
}
}
return null;
}
}
https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
[question]: 167. Two Sum II - Input array is sorted
Using the two-pointer technique:-
class Solution {
public int[] twoSum(int[] numbers, int target) {
if (numbers == null || numbers.length == 0)
return null;
int i = 0;
int j = numbers.length - 1;
while (i < j) {
int x = numbers[i] + numbers[j];
if (x < target) {
++i;
} else if (x > target) {
j--;
} else {
return new int[] { i + 1, j + 1 };
}
}
return null;
}
}
I have modified your code and added code comments on why your previous code has errors. Refer to code below for details.
public class Main {
public static void main(String[] args) {
int target = 9;
int[] numbers = new int[] { 2, 7, 11, 15 };
int[] result = twoSum(numbers, target);
if (result != null) {
System.out
.println("The sum of " + numbers[result[0]] + " and " + numbers[result[1]] + " is " + target + ".");
System.out.println("Therefore index1 = " + (result[0] + 1) + ", index2 = " + (result[1] + 1));
} else {
System.out.println("No Solution found!");
}
}
public static int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) { // array index starts at 0
for (int j = i + 1; j < numbers.length; j++) {
if (numbers[j] + numbers[i] == target) { // add the current numbers
// if (numbers[i] < numbers[j]) // not needed
return new int[] { i, j };
}
}
}
return null;
}
}
Sample input:
numbers = [2, 7, 11, 15];
Sample output:
The sum of 2 and 7 is 9.
Therefore index1 = 1, index2 = 2
You are starting first for-loop with i = 0, what you should do is start it with i = 1.
Working code:
public class Solution
{
public static void main(String[] args)
{
int[] num = {2,7,11,5};
int n = 13;
int[] answer = new int[2];
answer = twoSum(num,n);
if(answer != null)
for(int i=0;i<2;i++)
System.out.printf( answer[i] +" ");
}
public static int[] twoSum(int[] numbers, int target)
{
for (int i = 0; i < numbers.length; i++)
{
for (int j = i + 1; j < numbers.length; j++)
{
if (numbers[j] == target - numbers[i])
{
if(numbers[i] < numbers[j])
return new int[] { i+1, j+1};
}
}
}
return null;
}
}
Note: I have placed an IF before FOR in main() so that if we find no such integers that adds up to give target integer, it'll not throw a NullPointerException.
This is a better solution as it's much faster and covers all test cases as well:
class Solution {
public int[] twoSum(int[] numbers, int target) {
int l = 0, r = numbers.length - 1;
while (numbers[l] + numbers[r] != target) {
if (numbers[l] + numbers[r] > target)
r--;
else
l++;
if (r == l) return new int[]{};
}
return new int[]{l + 1, r + 1};
}
}
public int[] twoSum(int[] nums, int target) {
int start = 0, end = nums.length -1;
while (start < end){
if (nums[start]+ nums[end]== target)
return new int []{start+1, end+1};
if (nums[start]+ nums[end]> target){
end--;}
else if (nums[start]+ nums[end]< target){
start++;
}
}
return null;
}
I have an assignment where I have to implement heap sort, quick sort, and counting sort into my program. Currently I have no errors but my output is returning as false for my heap and counting sort. What mistakes am I making? How can they be fixed? Please help any feedback will be appreciated.
package sorting;
import java.util.*;
public class Sort2
{
public static int left (int i)
{
return 2 * i + 1;
}
public static int right (int i)
{
return 2 * i + 2;
}
public static int parent (int i)
{
return ((i-1)/2);
}
public static void max_heapify (int[] array, int heap_size, int i)
{
int largest = i;
int l = left(i);
int r = right(i);
if (l < heap_size && array[l] > array[i])
{
largest = l;
}
else
{
largest = i;
}
if (r < heap_size && array[r] > array[largest])
{
largest = r;
}
if (largest != i)
{
int exchange = array[i];
array[i] = array[largest];
array[largest] = exchange;
max_heapify(array, array.length, largest);
}
}
public static int[] build_heap (int[] array)
{
int heap_size = array.length;
for (int i = array.length/2; i >= 1;i--)
{
max_heapify(array, heap_size, i);
}
return array;
}
public static int[] heap_sort (int[] array)
{
build_heap(array);
int heap_size = array.length;
for (int i = array.length;i >= 2;i--)
{
heap_size--;
int exchange = array[0];
array[0] = array[heap_size];
array[heap_size] = exchange;
max_heapify(array, array.length, 1);
}
return array;
}
public static void quick_sort (int[] array, int p, int r)
{
if (p < r)
{
int q = partition(array, p, r);
quick_sort(array, p,q-1);
quick_sort(array, q + 1,r);
}
}
public static int partition (int[] array, int p, int r)
{
int x = array[r];
int i = p - 1;
for (int j = p;j< r;j++)
{
if (array[j] <= x)
{
i++;
int exchange = array[i];
array[i] = array[j];
array[j] = exchange;
}
}
int exchange = array[i+1];
array[i+1] = array[r];
array[r] = exchange;
return i + 1;
}
public static int[] counting_sort (int[] A, int k)
{
int [] C = new int[k+1];
int [] B = new int [A.length];
for(int i = 0;i <= k; i++)
{
C[i] = 0;
}
for(int j = 0; j < A.length; j++)
{
C[A[j]] = C[A[j]] + 1;
}
for (int i = 1; i <= k; i++)
{
C[i] = C[i]+C[i-1];
}
for (int j = A.length - 1;j > 1; j--)
{
B[C[A[j]]- 1]=A[j];
C[A[j]]=C[A[j]] - 1;
}
return B;
}
public static int[] generate_random_array (int n, int k) {
List<Integer> list;
int[] array;
Random rnd;
rnd = new Random(System.currentTimeMillis());
list = new ArrayList<Integer> ();
for (int i = 1; i <= n; i++)
list.add(new Integer(rnd.nextInt(k+1)));
Collections.shuffle(list, rnd);
array = new int[n];
for (int i = 0; i < n; i++)
array[i] = list.get(i).intValue();
return array;
}
public static int[] generate_random_array (int n) {
List<Integer> list;
int[] array;
list = new ArrayList<Integer> ();
for (int i = 1; i <= n; i++)
list.add(new Integer(i));
Collections.shuffle(list, new Random(System.currentTimeMillis()));
array = new int[n];
for (int i = 0; i < n; i++)
array[i] = list.get(i).intValue();
return array;
}
/*
* Input: an integer array
* Output: true if the array is acsendingly sorted, otherwise return false
*/
public static boolean check_sorted (int[] array) {
for (int i = 1; i < array.length; i++) {
if (array[i-1] > array[i])
return false;
}
return true;
}
public static void print_array (int[] array) {
for (int i = 0; i < array.length; i++)
System.out.print(array[i] + ", ");
System.out.println();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int k = 10000;
System.out.println("Heap sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000) {
int[] array = Sort2.generate_random_array(n);
long t1 = System.currentTimeMillis();
array = Sort2.heap_sort(array);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
boolean flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Heap sort ends ------------------");
//Currently works
System.out.println("Quick sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000)
{
int[] array = Sort2.generate_random_array(n);
long t1 = System.currentTimeMillis();
Sort2.quick_sort(array, 0, n-1);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
boolean flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Quick sort ends ------------------");
int[] array2 = Sort2.generate_random_array(10, 10);
array2 = Sort2.counting_sort(array2,10);
boolean flag = Sort2.check_sorted(array2);
System.out.println(flag);
System.out.println("Counting sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000) {
int[] array = Sort2.generate_random_array(n, k);
long t1 = System.currentTimeMillis();
array = Sort2.counting_sort(array, n);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Counting sort ends ------------------");
}
}
EDIT I modified your check method to print out the offending array elements:
public static boolean check_sorted( int[] array ) {
for( int i = 1; i < array.length; i++ ) {
if( array[i-1] > array[i] ) {
System.err.println( "Reversed array elements: " + (i-1) + "="
+ array[i-1] + ", " + i + "=" + array[i] );
return false;
}
return true;
}
It looks like the heap sort does not sort the first element of the array:
Heap sort starts ------------------
100000,5,false
Reversed array elements: 0=100000, 1=99999
And ten more like that.
For this homework assignment I would have suggested doing a google search on the specific sorts you were told to complete.
https://www.geeksforgeeks.org/counting-sort/
This will show you the code you just need to modify it for your variables. One thing I noticed right away is you are not building the count array correctly and that is affecting the build of the output array.
https://www.geeksforgeeks.org/heap-sort/
Here is the same instruction and explanation for your heap sort. I did not really look deeply into this as I do not have the time right now. Please use these resources to modify your code and hopefully complete the project.
This is my code:
long sum(int[] arr) {
long sum=0;
int j,k;
long sumtoadd;
for (int i = 0; i < arr.length; i++)
{
for (j = i; j < arr.length; j++)
{
sumtoadd = 0;
for (k = i; k <= j; k++)
{
sumtoadd = sumtoadd + arr[k];
}
sum = sumtoadd + sum;
}
}
return sum;
}
Example:
Array : {1,2,3} Output: 20
Array : {1,1,1} Output: 10
I am trying to find the sum of all contiguous subarrays of an array, but for some of the cases, time is exceeding. This solution is working for all cases except large sized cases. Is there any better solution for this?
public class Test1 {
static long sum2(int[] arr) {
long n = arr.length;
long sum = 0;
for (int i = 0; i < n; i++) {
sum += (n-i)*(i+1)*arr[i];
}
return sum;
}
static int[] arr1 = new int[]{1,2,3,4,5,6,7,8,9};
static int[] arr2 = new int[]{1,1,1,1};
public static void main(String[] args) {
System.out.println("sum(arr1) = " + sum(arr1));
System.out.println("sum2(arr1) = " + sum2(arr1));
System.out.println("sum(arr2) = " + sum(arr2));
System.out.println("sum2(arr2) = " + sum2(arr2));
}
//your code to check
static long sum(int[] arr) {
long sum=0;
int j,k;
long sumtoadd;
for (int i = 0; i < arr.length; i++)
{
for (j = i; j < arr.length; j++)
{
sumtoadd = 0;
for (k = i; k <= j; k++)
{
sumtoadd = sumtoadd + arr[k];
}
sum = sumtoadd + sum;
}
}
return sum;
}
}
Instead of three nested loops, the answer can be found in one loop over the N array elements.
Reasoning:
If a given array element A[i] occurs in K subarrays, then it contributes its value to K subarrays, meaning it contributes K-times its value to the total sum. Now the element A[i] occurs in all subarrays with a start from 0 to i (inclusive), and an end from i+1 to N (inclusive), so K = (i+1)*(N-i).
Summary: every A[i] contributes (i+1)*(N-i)*A[i]. Do that in a single loop, and you're finished.
I can search for subarrays with sum eqaul to k for positive numbers but the below code fails for negative numbers in arrays. Is there an algorithm for finding subarrays with a given sum for negative and positive numbers in an array ?
public static void subarraySum(int[] arr, int sum) {
int start=0;
int currSum=arr[0];
for(int i = 1;i<=arr.length;i++) {
while(currSum>sum ) {
currSum-=arr[start];
start++;
}
if(currSum==sum) {
System.out.println(start + " " + (i-1) + " index");
start=i;
currSum=0;
}
if(i<arr.length) {
currSum +=arr[i];
}
}
}
For example, {10, 2, -2, -20, 10}, find subarray with sum -10 in this array.
Subarray in this case would be {-20, 10}.
O(N^2) solution
For each index i precalculate the sum of subarray from 0 to i, inclusively. Then to find sum of any subarray (i, j) you can just calculate sum[j] - sum[i] + arr[i].
public static void subArraySum(int[] arr, int target) {
if (arr.length == 0) return;
int n = arr.length;
int[] sum = new int[n];
sum[0] = arr[0];
for (int i = 1; i < n; ++i) {
sum[i] = sum[i - 1] + arr[i];
}
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j)
if (sum[j] - sum[i] + arr[i] == target) {
System.out.println(i + " " + j);
}
}
Faster solution
You can find subarray faster if you will store the sums in the map and then query this map for the required sum.
public static void subArraySum(int[] arr, int target) {
if (arr.length == 0) return;
int n = arr.length;
int[] sum = new int[n];
sum[0] = arr[0];
for (int i = 1; i < n; ++i) {
sum[i] = sum[i - 1] + arr[i];
}
Map<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < n; ++i) {
if (sum[i] == target) {
System.out.println(0 + " " + i);
}
int requiredSum = sum[i] - target;
if (map.containsKey(requiredSum)) {
int startIndex = map.get(requiredSum) + 1;
System.out.println(startIndex + " " + i);
}
map.put(sum[i], i);
}
}
This solution is O(N*logN), but you can make it faster if you will use HashMap instead of TreeMap (O(N) if you assume that HashMap operations complexity is constant).
Note that this solution will not print all possible pairs. If you need to find all subarrays with given sum you need to have Map<Integer, Array<Integer>> instead of Map<Integer, Integer> and store all indexes with given sum.
I am trying to the length of the longest sequence of numbers shared by two arrays. Given the following two arrays:
int [] a = {1, 2, 3, 4, 6, 8,};
int [] b = {2, 1, 2, 3, 5, 6,};
The result should be 3 as the the longest common sequence between the two is{1, 2, 3}.
The numbers must be in a sequence for the program to consider to count it.
I have thought about it and wrote a small beginning however, I am not sure how to approach this
public static int longestSharedSequence(int[] arr, int[] arr2){
int start = 0;
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr2.length; j++){
int n = 0;
while(arr[i + n] == arr2[j + n]){
n++;
if(((i + n) >= arr.length) || ((j + n) >= arr2.length)){
break;
}
}
}
That is a very good start that you have. All you need to do is have some way of keeping track of the best n value that you have encountered. So at the start of the method, declare int maxN = 0. Then, after the while loop within the two for loops, check if n (the current matching sequence length) is greater than maxN (the longest matching sequence length encountered so far). If so, update maxN to the value of n.
Since you also want the matching elements to be in sequential order, you will need to check that the elements in the two arrays not only match, but that they are also 1 greater than the previous element in each array.
Putting these together gives the following code:
public static int longestSharedSequence(int[] arr, int[] arr2) {
int maxN = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr2.length; j++) {
int n = 0;
// Check that elements match and that they are either the
// first element in the sequence that is currently being
// compared or that they are 1 greater than the previous
// element
while (arr[i + n] == arr2[j + n]
&& (n == 0 || arr[i + n] == arr[i + n - 1] + 1)) {
n++;
if (i + n >= arr.length || j + n >= arr2.length) {
break;
}
}
// If we found a longer sequence than the previous longest,
// update maxN
if (n > maxN) {
maxN = n;
}
}
}
return maxN;
}
I didn't think of anything smarter than the path you were already on:
import java.util.Arrays;
import java.util.Random;
public class MaxSeq {
public static void main(String... args) {
int[] a = new int[10000];
int[] b = new int[10000];
final Random r = new Random();
Arrays.parallelSetAll(a, i -> r.nextInt(100));
Arrays.parallelSetAll(b, i -> r.nextInt(100));
System.out.println(longestSharedSequence(a, b));
}
private static int longestSharedSequence(final int[] arr, final int[] arr2) {
int max = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr2.length; j++) {
int n = 0;
while ((i + n) < arr.length
&& (j + n) < arr2.length
&& arr[i + n] == arr2[j + n]) {
n++;
}
max = Math.max(max, n);
}
}
return max;
}
}
see: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem