26. Remove Duplicates from Sorted Array - Java - java

Question : Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int i = 0;
for (int j = 1; j < nums.length; j++) {
if (nums[j] != nums[i]) {
i++;
nums[i] = nums[j];
}
}
return i + 1;
}
What exactly does the return statement do here. What does return i + 1 mean here ?

The return i + 1 is returning how many unique integers are there. I believe this is a Leetcode problem, and since its in place, the int[] is passed in by reference, Leetcode wants to know how many numbers to check (you're supposed to put the unique numbers in the first i + 1 spots).
If you look at the question, it says:
Which means that you return the length of the array.
So, if you have the array [1,1,2,3,4,4], you would turn that into [1,2,3,4,...], where the ... is the rest of the array. However, you return 4 because the length of the new array should be 4.
Hope this clears things up for you!

Your question has been already answered here; in addition to that, we can also start from zero and remove the first if statement:
Test with a b.java file:
import java.util.*;
class Solution {
public static final int removeDuplicates(
final int[] nums
) {
int i = 0;
for (int num : nums)
if (i == 0 || num > nums[i - 1]) {
nums[i++] = num;
}
return i;
}
}
class b {
public static void main(String[] args) {
System.out.println(new Solution().removeDuplicates(new int[] { 1, 1, 2}));
System.out.println(new Solution().removeDuplicates(new int[] { 0, 0, 1, 1, 1, 2, 2, 3, 3, 4}));
}
}
prints
2
5

I tried in this easy way. Here Time complexity is O(n) and space
complexity: O(1).
static int removeDuplicates(int[] nums){
if(nums.length == 0) {
return 0;
}
int value = nums[0];
int lastIndex = 0;
int count = 1;
for (int i = 1; i < nums.length; i++) {
if(nums[i] > value) {
value = nums[i];
lastIndex = lastIndex+1;
nums[lastIndex] = value;
count++;
}
}
return count;
}

class Solution {
public int removeDuplicates(int[] nums) {
int n = nums.length;
if (n == 0 || n == 1)
return n;
int j = 0;
for (int i=0; i<n-1; i++)
if (nums[i]!= nums[i+1])
nums[j++] = nums[i];
nums[j++]=nums[n-1];
return j;
}
}

public class RemoveDuplicateSortedArray {
//Remove Duplicates from Sorted Array
public static void main(String[] args) {
int[] intArray = new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4};
int count = extracted(intArray);
for (int i = 0; i < count; i++) {
System.out.println(intArray[i]);
}
}
private static int extracted(int[] intArray) {
int size = intArray.length;
int count = 1;
if (size == 1) {
return 1;
} else if (size == 2) {
if (intArray[0] == intArray[1]) {
return 1;
} else {
return 2;
}
} else {
for (int i = 0, j = i + 1; j < size; j++) {
if (intArray[i] < intArray[j]) {
i++;
intArray[i] = intArray[j];
count++;
}
}
return count;
}
}
}

Related

Longest Increasing Subsequence Length and Value

Below code gives the length of longest increasing subsequence. Code works fine.
Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
With the help of below code I want to print which array elements are part of the subsequence i.e [2,3,7,101],
How can I do it? Or do I need to write completely different code?
Is there any generic way to do for other problems to do like longest palindromic subsequence?
public int lengthOfLIS(int[] nums) {
return helper(nums, 0, Integer.MIN_VALUE);
}
public int helper(int[] arr, int i, int prev) {
if (i == arr.length)
return 0;
int include = 0;
if (arr[i] > prev) {
include = 1 + helper(arr, i + 1, arr[i]);
}
int exclude = helper(arr, i + 1, prev);
return Math.max(include, exclude);
}
public void longestIncreasingSubsequence(int[] numbers)
{
List<Integer> result = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
for (int i = 0; i < numbers.length; i++) {
temp.add(numbers[i]);
if ( i + 1 == numbers.length || numbers[i] > numbers[i + 1])
{
if(temp.size() >= result.size())
{
result.clear();
result.addAll(temp);
}
temp.clear();
}
}
System.out.println(result);
}
Try this
I got your point. Plz Check my new code
public void longestSubSequence(int[] nums)
{
int index=0;
List<Integer> result = new ArrayList<>();
while (index<nums.length)
{
int val=nums[index];
List<Integer> temp = new ArrayList<>();
temp.add(val);
for (int i = index+1; i < nums.length; i++) {
int currentVal = nums[i];
if (val < currentVal)
{
val= currentVal;
temp.add(currentVal);
}
}
if(temp.size()>= result.size())
{
result.clear();
result.addAll(temp);
temp.clear();
}
index++;
}
System.out.println(result);
}

Testing array issue

I am stuck on an issue that I cannot seem to resolve. I cannot seem to to test my code correctly. My code is as follows
public static int sum13( int[] nums) {
int sum = 0;
for(int i = 0; i <= nums.length - 1; i++){
if( nums[i] != 13){
sum += nums[i];
if(i > 0 && nums[i-1] == 13)
sum -= nums[i];
}
}
return sum;
}
public static void main(String[] args) {
}
If I try to put System.out.println(sum13([1,2,2,1]) I am met with several errors relating to the [] as well as the ,. I cannot figure out, what it is that I've done wrong.
Return the sum of the numbers in the array, returning 0 for an empty array. Except the number 13 is very unlucky, so it does not count and numbers that come immediately after a 13, also do not count. sum13([1, 2, 2, 1]) →6
sum13([1, 1]) →2
I decided to add flag to know when the previous value was 13. In that way, you don't have to deal with edge cases.
public static int sum13(int[] nums) {
int sum = 0;
boolean was13 = false;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 13) {
was13 = true;
} else {
if(!was13)
sum += nums[i];
was13 = false;
}
}
return sum;
}
A possible solution with some test cases:
public static int sum13(int[] numbers)
{
int sum = 0;
int prev = 0;
for (var number : numbers)
{
if (number != 13 && prev != 13)
{
sum += number;
}
prev = number;
}
return sum;
}
public static void main(String[] args)
{
System.out.println(sum13(new int[]{}));
System.out.println(sum13(new int[]{1, 2, 3, 4, 5}));
System.out.println(sum13(new int[]{13, 1, 13, 13, 2, 3, 4, 5}));
}

Returning the index of the n-th highest value of an unsorted list

I have written the following code and am now trying to figure out the best way to achieve what is explained in the four comments:
Integer[] expectedValues = new Integer[4];
for (int i = 0; i <= 3; i++) {
expectedValues[i] = getExpectedValue(i);
}
int choice = randomNumGenerator.nextInt(100) + 1;
if (choice <= intelligence) {
// return index of highest value in expectedValues
} else if (choice <= intelligence * 2) {
// return index of 2nd highest value in expectedValues
} else if (choice <= intelligence * 3) {
// return index of 3rd highest value in expectedValues
} else {
// return index of lowest value in expectedValues
}
What would be an elegant way o doing so? I do not need to keep expected values as an array - I am happy to use any data structure.
You could create a new array containing the indices and sort on the values - in semi-pseudo code it could look like this (to be adapted):
int[][] valueAndIndex = new int[n][2];
//fill array:
valueAndIndex[i][0] = i;
valueAndIndex[i][1] = expectedValues[i];
//sort on values in descending order
Arrays.sort(valueAndIndex, (a, b) -> Integer.compare(b[1], a[1]));
//find n-th index
int n = 3; //3rd largest number
int index = valueAndIndex[n - 1][0];
If you want to work with simple arrays, maybe this might be a solution:
public static void main(String[] args) {
int[] arr = new int[] { 1, 4, 2, 3 };
int[] sorted = sortedCopy(arr);
int choice = randomNumGenerator.nextInt(100) + 1;
if (choice <= intelligence) {
System.out.println(findIndex(arr, sorted[3])); // 1
} else if (choice <= intelligence * 2) {
System.out.println(findIndex(arr, sorted[2])); // 3
} else if (choice <= intelligence * 3) {
System.out.println(findIndex(arr, sorted[1])); // 2
} else {
System.out.println(findIndex(arr, sorted[0])); // 0
}
}
static int[] sortedCopy(int[] arr) {
int[] copy = new int[arr.length];
System.arraycopy(arr, 0, copy, 0, arr.length);
Arrays.sort(copy);
return copy;
}
static int findIndex(int[] arr, int val) {
int index = -1;
for (int i = 0; i < arr.length; ++i) {
if (arr[i] == val) {
index = i;
break;
}
}
return index;
}
You can "wipe out" the highest value n-1 times. After this the highest value is the n-th highest value of the original array:
public static void main(String[] args) {
int[] numbers = new int[]{5, 9, 1, 4};
int n = 2; // n-th index
for (int i = 0; i < n - 1; ++i) {
int maxIndex = findMaxIndex(numbers);
numbers[maxIndex] = Integer.MIN_VALUE;
}
int maxIndex = findMaxIndex(numbers);
System.out.println(maxIndex + " -> " + numbers[maxIndex]);
}
public static int findMaxIndex(int[] numbers) {
int maxIndex = 0;
for (int j = 1; j < numbers.length; ++j) {
if (numbers[j] > numbers[maxIndex]) {
maxIndex = j;
}
}
return maxIndex;
}
The complexity is O(n * numbers.length).

how to calculate mode for a sorted array in java

So I'm writing a method to calculate mode of a sorted array. But when i print out the mode value, it always comes out as 0.00, and i tried to fix it but could't.
Here's my code for this method:
(numRead is the passed array, num is the array length that actually have values)
public static void modeCalc(double[] numRead, int num)
{
double maxValue = numRead[0];
int maxCount = 0;
for (int i = 0; i < numRead.length; i++)
{
int count = 0;
for (int j = 0; j < numRead.length; j++)
{
if (numRead[j] == numRead[i])
count++;
}
if (count > maxCount)
{
maxCount = count;
maxValue = numRead[i];
}
}
return maxValue;
}
Any help is much appreciated!
This should work. You need to return a double, and you need to use num.
class ModeArray
{
public static void main(String[] args) {
double[] numRead = { 1, 2, 3, 3, 4, 4, 4, 5, 0, 0, 0, 0, 0 };
System.out.println(modeCalc(numRead, 8));
}
public static double modeCalc(double[] numRead, int num) {
double maxValue = numRead[0];
int maxCount = 0;
for (int i = 0; i < num; i++) {
int count = 0;
for (int j = 0; j < num; j++) {
if (numRead[j] == numRead[i]){
count++;
}
}
if (count > maxCount) {
maxCount = count;
maxValue = numRead[i];
}
}
return maxValue;
}
}
If you know the array is sorted, you should use this information.
public static double modeCalc(double[] numRead, int num) {
double maxValue = numRead[0];
double lastValue = maxValue;
int count = 1;
int maxCount = 1;
for (int i = 1; i < num; i++) {
if (numRead[i] == lastValue) {
count++;
} else {
count = 1;
lastValue = numRead[i];
}
if (count > maxCount) {
maxCount = count;
maxValue = lastValue;
}
}
return maxValue;
}
PS: Please don't use if-statement without braces. It makes it easier to add bugs, and harder to find them.
a cursory glance suggests that your array has more 0 values at the end of the sorted data and these become the mode. here is what appears to be the problem, it is stated that numRead is the sorted array, but it has only num values of significance. the loops search the array to the end, not for the number of elements that have good values. change numRead.length to num and see if that helps. also, try passing a full array (no empty elements) and see if it works any better. it is likely that the empty elements are initialized to zero and that there are more of these than any other value.

Solving codingBat 'evenOdd' with one loop in Java

The question is about Solving this problem from codingBat in Java.
Problem Statement:
Return an array that contains the exact same numbers as the given array, but rearranged so that all the even numbers come before all the odd numbers. Other than that, the numbers can be in any order. You may modify and return the given array, or make a new array.
evenOdd({1, 0, 1, 0, 0, 1, 1}) → {0, 0, 0, 1, 1, 1, 1}
evenOdd({3, 3, 2}) → {2, 3, 3}
evenOdd({2, 2, 2}) → {2, 2, 2}
The Problem is simple with 2 loops I attempted at solving it with 1 it got too lengthy I believe, is there any other efficient way to solve the above problem using 1 loop?
do not use collections!
My solution:
public int[] evenOdd(int[] nums) {
boolean oddFound=false;
int count=-1;
int oddGap=0;
for(int i=0;i<nums.length;i++)
{
if(!(oddFound)&(nums[i]%2==0))
continue;
if((!oddFound)&(nums[i]%2==1))
{
oddFound=true;
count=i;
continue;
}
if((oddFound)&(nums[i]%2==1))
{
oddGap++;
continue;
}
if((oddFound)&(nums[i]%2==0))
{
int temp=nums[count];
nums[count]=nums[i];
nums[i]=temp;
if(i>0)
i--;
if(oddGap>0)
{
oddGap--;
count+=1;
oddFound=true;
continue;
}
oddFound=false;
}
}
return nums;
}
Since creating a new array is allowed, and the order of the numbers is irrelevant, I would use the following approach:
public int[] evenOdd(int[] nums) {
int[] output = new int[nums.length];
int evenPos = 0;
int oddPos = nums.length-1;
for (int i : nums) {
if (i%2==0) {
output[evenPos++]=i;
} else {
output[oddPos--]=i;
}
}
return output;
}
Update: A somewhat less readable version that doesn't require an extra array (along the lines of what #Seelenvirtuose suggests, just without the extra loops)
public int[] evenOdd(int[] nums) {
int evenPos = 0;
int oddPos = nums.length-1;
while (true) {
if (evenPos>=oddPos || evenPos>=nums.length || oddPos<0) {
break;
}
if (nums[evenPos]%2==0) {
evenPos++;
}
if (nums[oddPos]%2!=0) {
oddPos--;
}
if (evenPos<oddPos && nums[evenPos]%2 != 0 && nums[oddPos]%2 == 0) {
int tmp = nums[evenPos];
nums[evenPos] = nums[oddPos];
nums[oddPos] = tmp;
oddPos--;
evenPos++;
}
}
return nums;
}
You do not need any temporary lists or array because you can reorder the elements in-situ.
This is a simple algorithm:
Define two pointers, left and right (initially set to the bounds of the array).
As long as left does not exceed right and nums[left] is even, increment left.
As long as right does not exceed left and nums[right] is odd, decrement right.
If left is still less than right, swap the elements at positions left and right.
Repeat 2,3,4 as long as left is still less than right.
Got it? Here some code:
public int[] evenOdd(int[] nums) {
// (1)
int left = 0;
int right = nums.length -1;
do {
// (2)
while (left < right && nums[left] % 2 == 0)
left += 1;
// (3)
while (right > left && nums[right] % 2 != 0)
right -= 1;
// (4)
if (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
} while (left < right); // (5)
return nums;
}
Okay! I finally jumped across this question which is actually closed but the solution by asker was almost there apart from failing in 2 cases which I fixed:
I commented out he code by asker which was making it fail in a couple of cases as seen in the question.
I think below is the simplest and most optimized solution:
public int[] evenOdd(int[] nums) {
int y=nums.length,x,a=0;
int temp=0;
for(x=0;x<y;x++)
{
if(nums[x]%2==0) {
if(a>(y-2))
return nums;
else{
//nums[a]=nums[a]+nums[x];
//nums[x]=nums[a]-nums[x];
//nums[a]=nums[a]-nums[x];
temp=nums[a];
nums[a]=nums[x];
nums[x]=temp;
a+=1;
}
}
return nums;
}
Traverse evenOdd from 0 to N.
for every even number encountered, copy it to the required position on the evenOdd array.
for every odd num encountered, store it in a separate array called oddnum.
After traversing the whole array, just copy the elements from oddnum to the Back of evenOdd.
Ex: evenOdd = {5,2,1,4}
Step 1. copy 5 to oddnum[0]
2. copy 2 to evenodd[0]
3. copy 1 to oddnum[1]
4. copy 1 to evenodd[1]
5. cpy oddnum[0] to evenOdd[2] and oddnum[1] to evenOdd[3]
Keeping to your restrictions, here's a one-loop answer:
public int[] evenOdd(int[] nums) {
int[] result = new int[nums.length];
int nextEven = 0;
int nextOdd = nums.length - 1;
for ( int num : nums )
{
if ( num % 2 == 0 )
result[ nextEven++ ] = num;
else
result[ nextOdd-- ] = num;
}
return result;
}
public int[] evenOdd(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] % 2 == 0) {
int temp = nums[i];
nums[i] = nums[count];
nums[count] = temp;
count++;
}
}
return nums;
}
public int[] evenOdd(int[] nums) {
Stack stack = new Stack();
int[] nums2 = new int[nums.length];
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 != 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 == 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
nums2[i] = (Integer) stack.pop();
}
return nums2;
}
In-place version (stable):
We continually search for te first and last invalid values (first odd, before last even) and keep swapping them until they cross:
public int[] evenOdd(int[] nums) {
int first = 0, last = nums.length - 1;
while (first < last) {
while ((first < last) && isOdd(nums[last])) last--;
while ((first < last) && !isOdd(nums[first])) first++;
swap(nums, first, last);
}
return nums;
}
boolean isOdd(int num) { return (num & 1) == 1; }
void swap(int[] nums, int i, int j) {
int copy = nums[i];
nums[i] = nums[j];
nums[j] = copy;
}
With auxiliaries (stable):
We partition the even and odd values in separate lists and concatenate them back:
public int[] evenOdd(int[] nums) {
List<Integer> evens = new ArrayList<Integer>(nums.length);
List<Integer> odds = new ArrayList<Integer>(nums.length);
for (int num : nums)
if (isOdd(num)) odds.add(num);
else evens.add(num);
int[] results = new int[nums.length];
int i = 0;
for (int num : evens) results[i++] = num;
for (int num : odds) results[i++] = num;
return results;
}
boolean isOdd(int num) { return (num & 1) == 1; }
Simplified solution which uses Srteam API:
public int[] evenOdd(int[] nums) {
int[] evenOddArr = new int[nums.length];;
int[] evenArr = Arrays.stream(nums).filter(x -> x % 2 == 0).toArray();;
int[] oddArr = Arrays.stream(nums).filter(x -> x % 2 != 0).toArray();
evenOddArr = java.util.stream.IntStream.concat(Arrays.stream(evenArr), Arrays.stream(oddArr))
.toArray();
return evenOddArr;
}
It passes all the tests on CodingBat:

Categories

Resources