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.
Related
My code is supposed to take the random number generated in the random method and sort them but it's only giving me one number.
My program is a random number generator that is supposed to make 1000 numbers that I can sort but my code only inserts one number into the array.
public static void main(String[] args) {
// write
int max = 1000;
int min=0;
int range = max - min + 1;
// generate random numbers within 1 to 10
for (int i = 0; i < 1000; i++) {
int rand = (int) (Math.random () * range) + min;
System.out.println ( rand );
int array[] = {rand};
int size = array.length;
for ( i = 0; i < size - 1; i++) {
int min1 = i;
for (int j = i + 1; j < size; j++) {
if (array[j] < array[min1]) {
min = j;
}
}
int temp = array[min1];
array[min1] = array[i];
array[i] = temp;
}
for (int k = 0; k < size; i++) {
System.out.print(" " + array[i]);
}
}
}
You need to break your program into separate steps:
Insert all the random numbers into the array
Sort the array
Print the contents of the array
Few problems I noticed:
Since you want to generate 1000 numbers from 1-10, max and min should have values of 10 and 1, respectively.
array should be declared before you start inserting values. It should also have a fixed size of 1000.
Your bubble sort algorithm also had some errors which led to incorrect output. If you wish to sort the array from greatest to least instead, simply change the > to < in the condition of the if statement.
I also decided to use Arrays.toString() to print the array instead of the loop.
public static void main(String[] args) {
int max = 10;
int min = 1;
int range = max - min + 1;
int size = 1000;
int[] array = new int[size];
for (int i = 0; i < size; i++) {
int rand = (int) (Math.random() * range + min);
array[i] = rand;
}
int temp = 0;
for (int i = 0; i < size; i++) {
for (int j = 1; j < size - i; j++) {
if (array[j - 1] > array[j]) {
temp = array[j - 1];
array[j - 1] = array[j];
array[j] = temp;
}
}
}
System.out.println(Arrays.toString(array));
}
your code will result an ArrayIndexOutException. below is the code change from your code ,i dont change too much so you can compare them and find your mistakes,wish good :D
public static void main(String[] args) {
int max = 1000;
int min=0;
int range = max - min + 1;
int[] array = new int[range];
// generate random numbers within 1 to 10
for (int i = 0; i < 1000; i++) {
int rand = (int) (Math.random () * range) + min;
array[i] = rand;
}
int size = array.length;
for (int i = 0; i < size; i++) {
int min1 = i;
for (int j = i + 1; j < size; j++) {
if (array[j] < array[min1]) {
min1 = j;//here min1
}
}
int temp = array[min1];
array[min1] = array[i];
array[i] = temp;
}
for (int k = 0; k < size; k++) {
System.out.print(" " + array[k]);
}
}
let me explain it more clearly,in the OP's code there has some questions,two majors:
one:
for ( i = 0; i < size - 1; i++) {
int min1 = i;
for (int j = i + 1; j < size; j++) {
if (array[j] < array[min1]) {
min = j;
}
}
int temp = array[min1];
array[min1] = array[i];
array[i] = temp;
}
will never run,because the array size is 1 ,so the for loop phrase will be ignore without running(mean for(int i = 0; i < 0; i++){....}).
two:
for (int k = 0; k < size; i++) {
System.out.print(" " + array[i]);
}
beacause the array size is 1,so when array[1] will throw index out exception.so the outermost loop will just run once then throw a exception.
:D
Complete the divisibleSumPairs function in the editor below. It should return the integer count of pairs meeting the criteria.
divisibleSumPairs has the following parameter(s):
n: the integer length of array ar
ar: an array of integers
k: the integer to divide the pair sum by
Print the number of (i, j) pairs where i < j and ar[i] + ar[j] is evenly divisible by k.
I don't know what is wrong, only some cases has worked
static int divisibleSumPairs(int n, int k, int[] ar) {
int count = 0;
for (int i=0; i<n; i++){
for (int j=0; j<n; j++){
if ((ar[i]<ar[j]) && ((ar[i]+ar[j])%k)== 0){
count++;
}
}
}
return count;
}
The main problem is that you check for ar[i] < ar[j] while the problem statement says i < j:
static int divisibleSumPairs(int n, int k, int[] ar) {
int count = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (i < j && (ar[i] + ar[j]) % k == 0) {
count++;
}
}
}
return count;
}
The algorithm can be further optimized to:
static int divisibleSumPairs(int n, int k, int[] ar) {
int count = 0;
for (int i = 0; i < n; i++){
for (int j = i + 1; j < n; j++){
if ((ar[i] + ar[j]) % k == 0) {
count++;
}
}
}
return count;
}
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 have a method which counts how many sums of 3 elements,which are equal to 0, does the array contains. I need help finding the way to stop counting the same triplets in the loop. For instance, 1 + 3 - 4 = 0, but also 3 - 4 +1 = 0.Here is the method:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if(binarySearch(A,sum))
{
count++;
}
}
}
return count;
edit: I have to use the Binary Search (the array is sorted).
Here is the binarySearch code:
private static boolean binarySearch(int A[],int y)
{
y=-y;
int max = A.length-1;
int min = 0;
int mid;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
return true;
}
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
return false;
You can avoid counting different triplets by making one assumption that we need to look for the triplets (x,y,z) with x < y < z and A[x] + A[y] + A[z] == 0.
So what you need to do is to modify the binarySearch function to return the number of index that greater than y and has A[z] == -(A[x] + A[y])
private static int binarySearch(int A[],int y, int index)
{
y=-y;
int max = A.length-1;
int min = index + 1;
int mid;
int start = A.length;
int end = 0;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
start = Math.min(start, mid);
max = mid - 1;
} else
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
int max = A.length - 1;
int min = index + 1;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
end = Math.max(end, mid);
min= mid + 1;
} else if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
if(start <= end)
return end - start + 1;
return 0;
}
So the new function binarySearch will return the total number of index that greater than index and has value equals to y.
So the rest of the job is to count the answer
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
count += binarySearch(A,sum, j);
}
}
return count;
}
Notice how I used two binary search to find the starting and the ending index of all values greater than y!
private static int counter(int A[]) {
int e = A.length;
int count = 0;
for (int i = 0; i < e; i++) {
for (int j = 1; (j < e - 1) && (i != j); j++) {
for (int k = 2; (k < e - 2) && (j != k); k++) {
if (A[i] + A[j] + A[k] == 0) {
count++;
}
}
}
}
return count;
}
private static int counter(int ints[]) {
int count = 0;
for (int i = 0; i < ints.length; i++) {
for (int j = 0; j < ints.length; j++) {
if (i == j) {
// cannot sum with itself.
continue;
}
for (int k = 0; k < ints.length; k++) {
if (k == j) {
// cannot sum with itself.
continue;
}
if ((ints[i] + ints[j] + ints[k]) == 0) {
count++;
}
}
}
}
return count;
}
To solve problem with binary search
Your code was almost correct. all you needed to do was just to replace
if (sum == binarySearch(A,sum)) {
with this
if (binarySearch(A,sum)) {
I am assuming that your binarySearch(A, sum) method will return true if it will found sum in A array else false
private static int counter(int A[]) {
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++) {
for (int j=i+1; j<e; j++) {
sum=A[i]+A[j];
if (binarySearch(A,sum)) {
count++;
}
}
}
return count;
}
Here is my solution assuming the array is sorted and there are no repeated elements, I used the binary search function you provided. Could the input array contain repeated elements? Could you provide some test cases?
In order to not counting the same triplets in the loop, we should have a way of inspecting repeated elements, the main idea that I used here is to have a list of int[] arrays saving the sorted integers of {A[i],A[j],-sum}.Then in each iteration I compare new A[i] and A[j] to the records in the list, thus eliminating repeated ones.
private static int counter(int A[]){
int sum;
int e = A.length;
int count = 0;
List<int[]> elements = new ArrayList<>();
boolean mark = false;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if (-sum == binarySearch(A,sum)){
int[] sort = {A[i],A[j],-sum};
if(-sum == A[i] || -sum == A[j]){
continue;
}else{
Arrays.sort(sort);
//System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]);
for (int[] element : elements) {
if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2])
mark = true;
}
if(mark){
mark = false;
continue;
}else{
count++;
elements.add(sort);
//System.out.println("Else sort" + sort[0] + " " + sort[1]);
}
}
}
}
}
return count;
}
you can use a assisted Array,stored the flag that indicate if the element is used;
Here is the code:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
// assisted flag array
List<Boolean> flagList = new ArrayList<Boolean>(e);
for (int k = 0; k < e; k++) {
flagList.add(k, false);// initialization
}
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
// if element used, no count
if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j))
{
count++;
flagList.set(i, true);
flagList.set(j, true);
}
}
}
return count;
I asked a question on helping me with this question about a week ago
Java permutations
, with a problem in the print permutation method. I have tidied up my code and have a working example that now works although if 5 is in the 5th position in the array it doesn't print it. Any help would be really appreciated.
package permutation;
public class Permutation {
static int DEFAULT = 100;
public static void main(String[] args) {
int n = DEFAULT;
if (args.length > 0)
n = Integer.parseInt(args[0]);
int[] OA = new int[n];
for (int i = 0; i < n; i++)
OA[i] = i + 1;
System.out.println("The original array is:");
for (int i = 0; i < OA.length; i++)
System.out.print(OA[i] + " ");
System.out.println();
System.out.println("A permutation of the original array is:");
OA = generateRandomPermutation(n);
printArray(OA);
printPermutation(OA);
}
static int[] generateRandomPermutation(int n)// (a)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
int swap = A[r];
A[r] = A[i];
A[i] = swap;
}
return A;
}
static void printArray(int A[]) {
for (int i = 0; i < A.length; i++)
System.out.print(A[i] + " ");
System.out.println();
}
static void printPermutation(int[] p)
{
int n = p.length-1;
int j = 0;
int m;
int f = 0;
System.out.print("(");
while (f < n) {
m = p[j];
if (m == 0) {
do
f++;
while (p[f] == 0 && f < n);
j = f;
if (f != n)
System.out.print(")(");
}
else {
System.out.print(" " + m);
p[j] = 0;
j = m - 1;
}
}
System.out.print(" )");
}
}
I'm not too crazy about
int n = p.length-1;
followed by
while (f < n) {
So if p is 5 units long, and f starts at 0, then the loop will be from 0 to 3. That would seem to exclude the last element in the array.
You can use the shuffle method of the Collections class
Integer[] arr = new Integer[] { 1, 2, 3, 4, 5 };
List<Integer> arrList = Arrays.asList(arr);
Collections.shuffle(arrList);
System.out.println(arrList);
I don't think swapping each element with a random other element will give a uniform distribution of permutations. Better to select uniformly from the remaining values:
Random rand = new Random();
ArrayList<Integer> remainingValues = new ArrayList<Integer>(n);
for(int i = 0; i < n; i++)
remainingValues.add(i);
for(int i = 0; i < n; i++) {
int next = rand.nextInt(remainingValues.size());
result[i] = remainingValues.remove(next);
}
Note that if order of running-time is a concern, using an ArrayList in this capacity is n-squared time. There are data-structures which could handle this task in n log n time but they are very non-trivial.
This does not answer the problem you have identified.
Rather i think it identifies a mistake with your generateRandomPermutation(int n) proc.
If you add a print out of the random numbers generated (as i did below) and run the proc a few times it allows us to check if all the elements in the ARRAY TO BE permed are being randomly selected.
static int[] generateRandomPermutation(int n)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
System.out.println("random nums generated are: ");
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
System.out.print(r + " ");
Run the proc several times.
Do you see what i see?
Jerry.