LeetCode Two Sum Problem - Multidimensional Array Help Java - arrays

I attempted the first LeetCode Problem: 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].
However, I keep getting a similar runtime error:
Finished in N/A
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at line 67, Solution.sortArr
at line 11, Solution.twoSum
I am not very used to using multidimensional arrays and saw this as the perfect opportunity to use them and learn. I've provided my code, could anyone help me figure out why this is failing?
class Solution {
public int[] twoSum(int[] nums, int target)
{
int[] targetIndex = {0,0};
int arrEndIndex = nums.length - 1;
int[][] copyArr = new int[nums.length][];
copyArr = copyArrWithIndex(nums);
int[][] sortedArr = new int[nums.length][];
sortedArr = sortArr(copyArr);
int firstIndex = 0;
int secondIndex = arrEndIndex;
int firstElement = 0;
int secondElement = 0;
while(firstIndex != secondIndex)
{
firstElement = sortedArr[firstIndex][0];
secondElement = sortedArr[secondIndex][0];
if(firstElement + secondElement == target)
{
targetIndex[0] = sortedArr[firstIndex][1];
targetIndex[1] = sortedArr[secondIndex][1];
break;
}
else if(firstElement + secondElement < target)
{
firstIndex++;
}
else
{
secondIndex--;
}
}
return targetIndex;
}
/*
This function sorts a 2D array of ints from least to greatest based
on the values in the first column and returns a 2D array of ints
*/
private int[][] sortArr(int[][] arr)
{
int temp = 0;
int firstIndex = 0;
int secondIndex = 1;
int firstElement = 0;
int secondElement = 0;
int i = 0;
while(i < arr[0].length)
{
firstElement = arr[firstIndex][0];
secondElement = arr[secondIndex][0];
if(firstElement < secondElement)
{
firstIndex++;
secondIndex++;
}
else /*if(firstElement > secondElement)*/
{
temp = firstElement;
arr[firstIndex][0] = secondElement;
arr[secondIndex][0] = temp;
temp = firstIndex;
arr[firstIndex][1] = secondIndex;
arr[secondIndex][1] = temp;
if(firstIndex != 0)
{
firstIndex--;
secondIndex--;
}
else
{
firstIndex++;
secondIndex++;
}
}
}
return(arr);
}
/*
This function accepts a 1D array and returns a 2D array of ints with the index int in the first
column and the original index of the presorted number adjacently in the second
column
*/
private int [][] copyArrWithIndex(int[] arr)
{
int[][] copyArr = new int [arr.length][2];
for(int i = 0; i < arr.length; i++)
{
copyArr[i][0] = arr[i];
copyArr[i][1] = i;
}
return(copyArr);
}
}

Related

Why is this below code giving heap overflow Error by just changing the comparison operator from &&(AND) to ||(OR)?

I was trying to solve below problem:
Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear as many times as it shows in both arrays and you may return the result in any order.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
Here is my code:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
for(int i=0; i<nums1Size-1; i++){
if(nums1[i]>nums1[i+1]){
int temp = nums1[i];
nums1[i] = nums1[i+1];
nums1[i+1] = temp;
i = -1;
}
}
for(int i=0; i<nums2Size-1; i++){
if(nums2[i]>nums2[i+1]){
int temp = nums2[i];
nums2[i] = nums2[i+1];
nums2[i+1] = temp;
i = -1;
}
}
int i = 0;
int j = 0;
int* res = (int*)malloc(10* sizeof(int));
int k = 0;
if(!(nums1Size > nums2Size)){
int * temp = nums1;
nums1 = nums2;
nums2 = temp;
int tempint = nums1Size;
nums1Size = nums2Size;
nums2Size = tempint;
}
while(i<nums1Size && j<nums2Size){
if(nums1[i] > nums2[j]){
j++;
}
else if(nums1[i] < nums2[j]){
i++;
}
else{
res[k++] = nums1[i];
i++; j++;
}
}
*returnSize = sizeof(res)/sizeof(res[0]);
return res;
}
To simplify the problem you have to solve, let's first write a helper function that counts the number of occurrences of a particular element inside an array:
int count_elem(int* arr, int n, int elem) {
int count = 0;
for (int i = 0; i < n; i += 1) {
if (arr[i] == elem) {
count += 1;
}
}
return count;
}
Now, let's try to solve the problem following the problem description:
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
// here we allocate `res` with size of the biggest array, because that's the worst case we'll have
int* res = malloc(sizeof(int) * ((nums1Size > nums2Size) ? nums1Size : nums2Size));
// just to be sure `malloc()` did not return an error
if (res == NULL) {
return NULL;
}
// we'll keep track of how many elements we actually put inside `res`
*returnSize = 0;
// let's loop through all elements of `nums1`
for (int i = 0; i < nums1Size; i += 1) {
int elem = nums1[i];
// if we already put the element inside `res`, we skip this cycle
int count_res = count_elem(res, *returnSize, elem);
if (count_res > 0) {
continue;
}
// let's count the occurrences in both arrays
int count1 = count_elem(nums1, nums1Size, elem);
int count2 = count_elem(nums2, nums2Size, elem);
// let's calculate how many times the element must be present inside `res`
// i.e.: the same number of times of the array with the fewer occurrences of it
// NOTE: if `nums1` or `nums2` do not include the element, we also don't include it inside `res`
int count_min = (count1 < count2) ? count1 : count2;
// now let's put inside `res` as many times as we previously calculated
for (int i = 0; i < count_min; i += 1) {
res[*returnSize] = elem;
*returnSize += 1;
}
}
return res;
}
Let's try if it works:
int main(void) {
int arr1[] = {1, 2, 2, 1};
int arr2[] = {2, 2};
int res_size;
int* res = intersect(arr1, sizeof(arr1) / sizeof(arr1[0]), arr2, sizeof(arr2) / sizeof(arr2[0]), &res_size);
// let's print the result of `intersect()`
for (int i = 0; i < res_size; i += 1) {
printf("%d\n", res[i]);
}
return 0;
}
Output:
2
2
NOTE: the function is not optimized for speed nor for memory efficiency. This will be left as an exercise for the reader.
UPDATE
The previous version of the answer was wrong (sorry again). Now it should be correct.

why is the sort function not sorting a struct?

I have the pair struct below which contains two variables:
typedef struct
{
int winner;
int loser;
}
pair;
And I am trying to sort them according to the array pair_strength which is in the same length. However, while the sorting function seems fine, the ordering of the pair struct is not changing at all. Below is the sort function:
int pair_strength[] = {1, 5, 2, 4, 3};
void sort_pairs(void)
{
// bubble sort
for (int i = 0; i < pair_count-1; i++)
{
for (int j = 0; j < pair_count-i-1; j++)
{
if (pair_strength[j] < pair_strength[j+1])
{
int temp_w = pairs[j].winner;
int temp_l = pairs[j].loser;
pairs[j].winner = pairs[j+1].winner;
pairs[j].loser = pairs[j+1].loser;
pairs[j+1].winner = temp_w;
pairs[j+1].loser = temp_l;
}
}
}
}
Therefore, given that 5 is the second element in pair_strength and is the biggest number, I want to move the second elements in both variables ( winner and loser) in pair struct to the first and so on
Thank you all for your help. Below is updated function:
void sort_pairs(void)
{
// bubble sort
for (int i = 0; i < pair_count-1; i++)
{
for (int j = 0; j < pair_count-i-1; j++)
{
if (pair_strength[j] < pair_strength[j+1])
{
pair t = pairs[j];
pairs[j] = pairs[j+1];
pairs[j+1] = t;
int t2 = pair_strength[j];
pair_strength[j] = pair_strength[j+1];
pair_strength[j+1] = t2;
}
}
}
}

Populate 2D array from a particular coordinate

I am trying to populate a 2D array vertically or horizontally from a given coordinate, if the indexes are in range.
Below is the program I can think about as of now.
I just want to know if there is any other optimized way to perform this logical operation.
public static void Main()
{
var arr = new string[10,10];
int x = 0;
int y = 1;
int len = 5;
string somevalue = "x";
string align = "vertical";
int i = x;
int j = y;
try
{
while(len > 0)
{
arr[i,j] = somevalue;
if(align == "vertical")
j++;
else
i++;
len--;
}
}
catch(IndexOutOfRangeException ex)
{
Console.WriteLine(ex);
}
}

How to find top 6 elements in an array in C

I am trying to find top 6 elements from an array with their ordering number.
int x=0;
for (int k = 0; k < 6; k++) //
{
for (i = 1; i <= 90; i++)
{
if (sorted[k] < holder[i] && i >= x)
{
sorted[k] = holder[i];
x = i; //
}
}
}
But this does not work. I want it to give me output like 43->7 15 ->3 etc..
Haven't written C in a while, but here is a simple solution that modifies the array in place and uses selection sort to select the k highest numbers in the array and moves them to the front. It keeps an array of indices that correspond to where the number originally was and applies the same swaps to it.
#include <stdio.h>
#define ELEMENTS 10
void main(void)
{
// example input for execution
int numbers[10] = {9,4,5,1,8,2,3,6,0,7};
// tracks ordering of indices
int indexes[10] = {0,1,2,3,4,5,6,7,8,9};
int k = 6;
int i, j;
int max, temp;
// Partial selection sort, move k max elements to front
for (i = 0; i < k; i++)
{
max = i;
// Find next max index
for (j = i+1; j < ELEMENTS; j++)
{
if (numbers[j] > numbers[max]) {
max = j;
}
}
// Swap numbers in input array
temp = numbers[i];
numbers[i] = numbers[max];
numbers[max] = temp;
// Swap indexes in tracking array
temp = indexes[i];
indexes[i] = indexes[max];
indexes[max] = temp;
}
for (i = 0; i < k; i++) {
printf("%d -> %d\n", indexes[i], numbers[i]);
}
}
And the output:
0 -> 9
4 -> 8
9 -> 7
7 -> 6
2 -> 5
1 -> 4
Here's the answer I have for you.
I would love some constructive criticism on it from anyone who can provide some.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *ptrNumbers[10];
int i=0;
for(; i < 10; i++){
ptrNumbers[i] = &numbers[i]; // assign the addresses
}
int topSix[6];
int topSixIndex=0;
for(; topSixIndex < 6; topSixIndex++){
int **best = NULL; // Pointer to the pointer to the value.
int checkIndex=0;
for(; checkIndex < 10; checkIndex++){
if(ptrNumbers[checkIndex] != NULL){
if(!best){
/* best is not yet defined */
best = &ptrNumbers[checkIndex];
// best now points to the pointer for numbers[checkIndex]
}else if(*ptrNumbers[checkIndex] > **best){
// this else if statement could be attached to the main if as
// an or condition, but I've separated it for readability.
best = &ptrNumbers[checkIndex];
// best now points to the pointer for numbers[checkIndex]
}
}
}
// assign the topSix position and flag the ptrNumbers
topSix[topSixIndex] = **best;
*best = NULL;
}
// now we'll print the numbers
for(topSixIndex = 0; topSixIndex < 6; topSixIndex++){
printf("%d\n", topSix[topSixIndex]);
}
return 0;
}
Essentially the program works like this: Given an array of ten numbers, a second array is constructed to house pointers to those 10 numbers. A third array is then constructed to house the values of the top 6 numbers. A for loop is then initialized to loop 6 times to find the highest unrecorded value. When the highest value is found by looping the pointer array, the value is assigned to the next index of the top six array. Once that value is added, the pointer array's index that points to the top six value is then assigned to NULL. This acts as a flag insuring that the value will not be added again. Finally, all numbers are printed out.
After running this code, the output I received was:
9
8
7
6
5
4
Edit: as a note, the ordering number's can be stored in a second array. You would simply need to track the checkIndex of the highest value and then assign it to a second array which contained the index values.
maybe you aren't looking for a code-only answer, but this will work:
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// return index of max element
int max_index( int* vec, int sz )
{
int idx, max, i;
if(!sz) return -1;
idx = 0;
max = vec[0];
for(i=1; i<sz; ++i)
{
if( vec[i] > max )
{
max = vec[i];
idx = i;
}
}
return idx;
}
// return indexes of N top elements
void top( int* vec, int sz, int* out_vec, int N )
{
int i, *tmp, idx;
tmp = (int*) malloc( sz*sizeof(int) );
memcpy( tmp, vec, sz*sizeof(int) );
for(i=0; i<N; ++i )
{
idx = max_index(tmp,sz);
out_vec[i]=idx;
tmp[idx] = INT_MIN;
}
free(tmp);
}
see it live here
Make an array of struct that contain data and index, then sort it and pick up first or last 6 elements to output.
Say that you are given an array numbers. Then create an array indexes with the same size as numbers in such a way that its values are equal to their indexes. Here is an illustration:
numbers = [ 1, 7, 3, 9, 2, 0 ]
indexes = [ 0, 1, 2, 3, 4, 5 ]
Sort numbers in descending order, performing the same operations on indexes. In the end, you should end up with something like this:
numbers = [ 9, 7, 3, 2, 1, 0 ]
indexes = [ 3, 1, 2, 4, 0, 5 ]
Finally, all you need to do is work with the first six elements of these arrays.
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int contains(int array[], int array_size, int value)
{
int i;
for (i = 0; i < array_size; i++)
{
if (array[i] == value)
{
return TRUE;
}
}
return FALSE;
}
int main()
{
int numbers[] = { 1, 7, 3, 9, 2, 0 };
int indexes[] = { 0, 1, 2, 3, 4, 5 };
int numbers_size = 6;
int largest[] = { -1, -1, -1, -1, -1, -1 };
int largest_index = 0;
int i;
for (i = 0; i < 6; i++)
{
int j;
int max_index = -1;
int max = -2147483648;
for (j = 0; j < numbers_size; j++)
{
if (numbers[j] >= max && contains(largest, numbers_size, j) == FALSE)
{
max_index = j;
max = numbers[max_index];
}
}
largest[largest_index++] = max_index;
}
for (i = 0; i < 6; ++i)
{
printf("%d->%d\n", largest[i], numbers[largest[i]]);
}
return 0;
}
You probably should use bubblesort (and keep a function holding all the original indexes) and then just make it show the 6 first number of both arrays (from the indexes array and from the array you sorted itself)

how to find complete sorting of elements by frequency?

Here is the problem:
Given an array of integers, sort the array according to frequency of elements. For example, if the input array is {2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12}, then modify the array to {3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5}. if 2 numbers have same frequency then print the one which came 1st.
I know how to do it partially. Here is my approcach.
I will create a struct which will be like:
typedef struct node
{
int index; // for storing the position of the number in the array.
int count; // for storing the number of times the number appears
int value; // for storing the actual value
} a[50];
I will create an array of these structs, I will then sort it by a sorting algorithm on the basis of their count. However, how can I ensure that if the frequency of two elements are same, then that number should appear which has a lesser index value?
#include <stdlib.h> // qsort, malloc, free
#include <stddef.h> // size_t
#include <stdio.h> // printf
struct number
{
const int * value;
int num_occurrences;
};
static void cmp_by_val(const struct number * a, const struct number * b)
{
if (*a->value < *b->value)
return -1;
else if (*b->value < *a->value)
return 1;
else
return 0;
}
static void cmp_by_occurrence_stable(const struct number * a, const struct number * b)
{
if (a->num_occurrences < b->num_occurrences)
return -1;
else if (b->num_occurrences < a->num_occurrences)
return 1;
else if (a->value < b->value)
return -1;
else if (b->value < a->value)
return 1;
else
return 0;
}
static struct number * sort_by_occurrence(const int * arr, size_t N)
{
//
// STEP 1: Convert the input
//
struct number * sort_arr = (struct number *)malloc(N * sizeof(struct number));
if (! sort_arr) return NULL;
for (int k = 0; k < N; ++k)
{
sort_arr[k].value = &arr[k];
sort_arr[k].num_occurrences = 0;
}
//
// STEP 2: Sort the input based on value
//
qsort(sort_arr, N, sizeof(struct number), cmp_by_val);
//
// STEP 3: Count occurrences
//
if (0 < N)
{
int cur_value = *sort_arr[0].value;
int i = 0;
for (j = 1; j < N; ++j)
{
if (*sort_arr[j].value != *sort_arr[i].value)
{
for (int k = i; k < j; ++k)
sort_arr[k].num_occurrences = j - i;
i = j;
}
}
for (; i < N; ++i)
sort_arr[i].num_occurrences = N - i;
}
//
// STEP 4: Sort based on occurrence count
//
qsort(sort_arr, N, sizeof(struct number), cmp_by_occurrence_stable);
//
// DONE
//
return sort_arr;
}
static void print_arr(const struct number * arr, size_t N)
{
if (0 < N)
{
printf("%d", arr[0]->value);
for (int k = 1; k < N; ++k)
printf(", %d", arr[k]->value);
}
printf("\n");
}
int main(int argc, char ** argv)
{
const int EXAMPLE_INPUT[11] = { 2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12 };
struct number * sort_arr = sort_by_occurrence(EXAMPLE_INPUT, 11);
if (sort_arr)
{
print_arr(sort_arr, 11);
free(sort_arr);
}
};
You could create an array which stores the frequency of your input array (i.e. frequency[i] is the frequency of the input[i] element). After that it is easy to order the frequency array (using an stable algorithm) and make the same changes (swaps?) to the input array.
For creating the frequency array you can use several approaches, a simple and inefficient one is just counting each element with two nested loops. I left more efficient alternatives to your imagination.
Note: the frequency array has the same function as the count field in your struct node, but in a separated memory. If you will not need the frequencies in the future, I recommend you to use the separated memory, as you can release it.
It seems that the problem is using unstable sort algorithm on the frequency of array elements.
Do a qsort on the array based on freq
Again do a qsort on the resulted array based on the indexes of the element with the same freq only.
This should give you a correct answer in O(nLog)
I minimized the code. The obvious parts are left out.
struct node
{
int *val;
int freq;
// int index; <- we can do this by comparing &a->val with &b->val
};
int compare_byfreq(const int* a, const int* b)
{
return a->freq - b->freq;
}
int compare_index(const int* a, const int* b)
{
if( a->freq == b->freq)
{
return a->val - b->val; //this can never be zero
}
//else we have different freq don't move elem
return 0;
}
int main()
{
int arr[] = {2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12};
node *narray = (struct node*)malloc(sizeof(arr) * sizeof(node));
// build the nodes-array
for(int i =0; i < sizeof(arr); i++)
{
/* buid narray here, make sure you store the pointer to val and not the actual values */
}
qsort(narray, sizeof(arr), compare_byfreq);
qsort(narray, sizeof(arr), compare_index);
/*print narray*/
return 0;
}
Edit: #0xbe5077ed got an interesting idea. Instead of comparing indexes compare addresses of your values! - I just re-edited the code for that
I was trying to learn Java nowadays, realized that this could be a good exercise. Tried and solved this problem over there in Eclipse. Java is horrible, I went back to C to solve it, here's a solution that I'll explain right after showing it:
#include <stdio.h>
#include <malloc.h>
typedef struct numbergroup {
int firstencounteridx;
int count;
int thenumber;
} Numbergroup;
int firstoneissuperior( Numbergroup gr1, Numbergroup gr2 ) {
return gr1.count > gr2.count || // don't mind the line-break, it's just to fit
( gr1.count == gr2.count && gr1.firstencounteridx < gr2.firstencounteridx );
}
void sortgroups( Numbergroup groups[], int amount ) {
for ( int i = 1; i < amount; i++ ) {
for ( int j = 0; j < amount - i; j++ ) {
if ( firstoneissuperior( groups[j + 1], groups[j] ) ) {
Numbergroup temp = groups[j + 1];
groups[j + 1] = groups[j];
groups[j] = temp;
}
}
}
}
int main( ) {
int input[] = { 2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12 };
Numbergroup * groups = NULL;
int amountofgroups = 0;
for ( int i = 0; i < ( sizeof input / sizeof * input ); i++ ) {
int uniqueencounter = 1;
for ( int j = 0; j < amountofgroups; j++ ) {
if ( groups[j].thenumber == input[i] ) {
uniqueencounter = 0;
groups[j].count++;
break;
}
}
if ( uniqueencounter ) {
groups = realloc( groups, ( amountofgroups + 1 ) * sizeof * groups );
groups[amountofgroups].firstencounteridx = i;
groups[amountofgroups].count = 1;
groups[amountofgroups].thenumber = input[i];
amountofgroups++;
}
}
sortgroups( groups, amountofgroups );
for ( int i = 0; i < amountofgroups; i++ )
for ( int j = 0; j < groups[i].count; j++ )
printf( "%d ", groups[i].thenumber );
free( groups );
putchar( 10 );
return 0;
}
Let me explain the structure first, as well as its functionality: It is for each unique number. In your example, it is for 2s, 3s, 4s, 5s and the 12s, one for each, 5 in total. Each one is to store:
the index of the first encounter of that number
the amount of encounter of that number
the value of that number
For example, for 12s, it shall store:
firstencounteridx as 5, that is the index of the first 12
count as 2
thenumber as 12
The first loop generally does that. It expands the group of Numbergroups whenever a unique number is encountered, stores its index as well; increases the count in case a number that already has a group has been encountered.
Then a sort is issued, which simply is a bubble sort. Might be different than the conventional one, I don't have any memorized.
Sorting criteria function simply checks if the count field of the first group is greater than the other; otherwise it checks whether they are the same and the firstencounter of the first group is earlier than the other; in which cases it returns 1 as true. Those are the only possible ways for the first group to be considered superior than the second one.
That's one method, there can be others. This is just a suggestion, I hope it helps you, not just for this case, but in general.
Created a map and sort the map by value.
O(nlogn) time, and O(n) space.
import java.util.*;
public class SortByFrequency {
static void sortByFreq( int[] A ) {
// 1. create map<number, its count>
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < A.length; i++) {
int key = A[i];
if( map.containsKey(key) ) {
Integer count = map.get(key);
count++;
map.put(key, count);
}
else {
map.put(key, 1);
}
}
// 2. sort map by value in desc. order
// used modified (for desc. order) MapUtil in http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java
Map<Integer, Integer> map2= MapUtil.sortByValue(map);
for(Map.Entry<Integer, Integer> entry : map2.entrySet() ) {
int num = entry.getKey();
int count = entry.getValue();
for(int i = 0; i < count; i++ ) {
System.out.print( num + " ");
}
}
System.out.println();
}
public static void main(String[] args ) {
int[] A1 = {2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12};
sortByFreq(A1);
}
}

Resources