The question asks to write static method sumNeighbours which takes an array of integers as an argument and returns an array with the same number of elements as the original array such that each integer in the new array is the sum of its neighbours and itself in the original array.
e.g.
[10, 20, 30, 40]
will be
[30, 60, 90, 70]
30(10+20) 60(20+10+30) 90(30+20+40) 70(40+30)
Thanks. Here's the code I've done and it works, BUT only for SOME cases, not ALL. Can anyone recommend a more efficient way to approach this? Without hard-coding all those if's and else's for certain cases.
public static int[] sumNeighbours(int[] values) {
int[] list = new int[values.length];
for (int i=0; i<values.length; i++) {
if (values.length > 1) {
if (values[i] == values[0]) {
list[i] = values[i] + values[i+1];
}
else if (values[i] == values[values.length-1]) {
list[i] = values[i] + values[i-1];
}
else {
list[i] = values[i] + values[i-1] + values[i+1];
}
}
else {
list [i] = values[i];
}
}
return list;
}
First: your input may be null, so null check first and I guess return null in that case.
Second: after creating an array of the same size you need to iterate the input and for each index check two things:
If index is smaller than (length-1) add the element on the right
If the index is greater than 0 add the element on the left
Always add the element in the current index
Done?
Don't use values to check if the element is either first of last, use the indexes and also have a nullptr check. Your code will fail for cases like [30,30,30]
public static int[] sumNeighbours(int[] values) {
if (null == values)
return null;
int[] list = new int[values.length];
for (int i=0; i<values.length; i++) {
if (values.length > 1) {
if (i == 0) {
list[i] = values[i] + values[i+1];
}
else if (i == values.length-1) {
list[i] = values[i] + values[i-1];
}
else {
list[i] = values[i] + values[i-1] + values[i+1];
}
}
else {
list [i] = values[i];
}
}
return list;
}
More efficiency way if you remove your if blocks within your loop:
public static int[] sumNeighbours(final int[] values) {
if (null == values || 2 > values.length) {
return values;
}
final int len = values.length;
final int[] list = new int[len];
list[0] = values[0] + values[1];
list[len - 1] = values[len - 2] + values[len - 1];
for (int i = 1; i < len - 2; i++) {
list[i] = values[i - 1] + values[i] + values[i + 1];
}
return list;
}
You do not need summary 3 numbers on the edges.
Check this Out,
public static int[] sumNeighbours(int[] values) {
int[] list = new int[(values.length)];
for (int i=0; i<values.length; i++) {
if (values.length > 1) { //To Check if there are more than one values
if(i==0) //It will check if it is first element
{
list[i]=values[i]+values[i+1]; //Add First value and second value to place it in first location. As first location has only one Neighbor
}
else if (i==(values.length-1)) //TO check If its last value
{
list[i]=values[i]+values[i-1]; //As Last Location has only one Neighbor
}
else
{
list[i]=values[i]+values[i-1]+values[i+1]; //For All intermediate locations
}
}
}
return list;
}
Here's the code I've done and it works, BUT only for SOME cases, not ALL
Probably it's because you compare values rather than indices: if (values[i] == values[0]) must be if (i == 0) and if (values[i] == values[values.length-1]) must be if (i == values.length - 1).
And snippet with less code and null-check may looks as follows
public static int[] sumNeighbours(int[] input) {
if (input == null) {
return null;
}
int[] result = new int[input.length];
for (int i = 0; i < input.length; i++) {
int sum = input[i];
if (i > 0) {
sum += input[i - 1];
}
if (i < (input.length - 1)) {
sum += input[i + 1];
}
result[i] = sum;
}
return result;
}
Related
I'm currently trying to solve the "three sum" challenge (I'm using java by the way). Here is the challenge description:
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
Here is my attempted solution but it is not working currently:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> subList = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
}
}
}
}
result.add(subList);
return result;
}
}
The output I'm getting is:
[[-1,0,1,-1,2,-1,0,1,-1]]
When it is supposed to be:
[[-1,-1,2],[-1,0,1]]
I know my attempted solution is O(n^(3)) and not optimal, but I'm curious on how I can do this challenge using three for loops. Can someone give me an idea on how I can go about creating the right output ? I've been trying different things to no avail. Thank you !
After finding a solution, pleas instantly add it to the results list:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> subList = new ArrayList<>();
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
result.add(subList);
}
}
}
}
return result;
}
}
This will give you:
[[-1,0,1],[-1,2,-1],[0,1,-1]]
In this case, the [-1,0,1] option is added twice, because -1 is in the list twice, depending whether or not you want this, you can sort the sublist, and check for equality:
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> subList = new ArrayList<>();
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
Collections.sort(subList);
boolean duplicate = false;
for (List<Integer> list : result) {
if (list.equals(subList)) {
duplicate = true;
break;
}
}
if (!duplicate) {
result.add(subList);
}
}
}
}
}
return result;
}
}
Put result.add(subList) inside of your if statement after your subList.add() statements. Currently in your code, you are adding every solution to the sublist without ever adding it to the result, so at the end you simply are adding a list of ints.
You have 2 issues here:
result.add(subList); You're adding your sublist at the very end of the computations.
You never clear previous results from your sublist.
You need to declare:
List<Integer> subList = new ArrayList<>();
Inside the 2nd loop and before the 3rd one AND add your sublist after you've added all 3 numbers but only if there was a coincidence (i.e. all 3 numbers added are equal to zero)
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
List<Integer> subList = new ArrayList<>();
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
}
}
if (!subList.isEmpty()) {
result.add(subList);
}
}
}
This provides this result:
[[-1, 0, 1], [-1, 2, -1], [0, 1, -1]]
And now we need to have them as unique combinations, so, we could use:
Collections.sort(sublist)
And change our result variable to be a Set rather than a List, so, our code will end up as:
import java.util.*;
class Solution {
public static Set<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> result = new HashSet<>();
for (int i = 0; i < nums.length - 2; i++) {
for (int j = i + 1; j < nums.length - 1; j++) {
List<Integer> subList = new ArrayList<>();
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
}
}
Collections.sort(subList);
if (!subList.isEmpty()) {
result.add(subList);
}
}
}
return result;
}
public static void main(String[] args) {
System.out.println(threeSum(new int[] {-1, 0, 1, 2, -1, -4}));
}
}
This returns:
[[-1, -1, 2], [-1, 0, 1]]
Note: I made the method static in order to test the program without creating an instance of the class.
You have two problems. The first and most obvious is that you've merely appended the elements to the array, without making a 3-element sub-array from them. You can fix that easily:
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
Should be
subList.add([nums[i], nums[j], nums[k]);
The second problem is that your program doesn't recognize that the -1 values are not considered separate solutions to the remaining pair of [1, 0]. The easiest way to get around this is to sort the list before you begin, and check that your third element can be only one of any grouping.
Finally, to consolidate the gains of that sorting, your loop nesting should ensure that you never pick the same elements in a different order. You're handling your indexing correctly, but eliminate the third loop. Merely check to see whether the sum you need is available. In pseudo-code ...
if (-(nums[i] + nums[j]) is in nums[j+1:])
kotlin way
fun main() {
println(ThreeSum(readLine()))
}
fun ThreeSum(nums: Array<Int>): Boolean {
if(nums.size < 4) return false //minimum 4 elements should be in array
var counter = 0
for (i in 0..(nums.size - 3)) {
for (j in (i + 1)..(nums.size - 3)) {
for (k in (j + 1)..(nums.size-1)) {
if (nums[i] + nums[j] + nums[k] == nums[0]) {
counter+=1
if (counter == 3) {
return true
}
}
}
}
}
return false
}
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> three=new ArrayList<>();
for(int i=0;i<nums.length-2;i++){
for(int j=i+1;j<nums.length-1;j++){
for(int k=j+1;k<nums.length;k++){
List<Integer> list=new ArrayList<>();
if(nums[i]+nums[j]+nums[k]==0){
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
Collections.sort(list);
boolean duplicate = false;
for (List<Integer> l : three) {
if (three.equals(list)) {
duplicate = true;
break;
}
}
if (!duplicate) {
if(!three.contains(list)){
three.add(list);
}
}
}
}
}
}
return three;
}
}
int count = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
if (arr[i] == arr[j] && i != j) {
return false;
}else count++;
}
} return (count == 3);
Task: Given an integer denoting the size of the array.Fill array with integers and return true if array contains duplicate 3 times next to each other.
This code does not Works fine. Given true if found duplicates 2 times.I need three times,and next to each other!! Some1 could help me please?!
What's about this:
for (int i = 0; i < arr.length - 2; i++) {
if (arr[i] == arr[i + 1] && arr[i] == arr[i + 2]) {
return true;
}
}
return false;
Solution using ArrayList to store the matching numbers,
int[] arryOne={1,2,3,4,4,4,5,5,5,6,6,7,7,7,8,9,9,9,19,19,19,21,21,30,45,10,10,10};
ArrayList<Integer> arryTwo=new ArrayList<Integer>();
for (int x=0;x<=arry.length-1;x++)
{
if(arryOne[x]==arryOne[x+1] && arryOne[x]==arryOne[x+2] && x!=arry.length-2)
{
arryTwo.add(arry[x]);
x=x+2;
}
}
System.out.println("The number which is repeating three times in the array is = ");
for (int valInArrayList: arryTwo)
{
System.out.print(valInArrayList + ", ");
}
for(int i=0;i<arr.length-2;i++){
if((arr[i]==arr[i+1])&& (arr[i]==arr[i+2])){
return true;
}
}
return false;
This way, we only check the array once, and this improve performances. What we do here in plain english is : "Check if a number is equal to the two following him", and we stop before going out of the array (this is what array.length-2 is for)
Ex: for an array of 6 numbers, we will check
[0,1,2]
[1,2,3]
[2,3,4]
[3,4,5]
public class LoopTest {
public static void main(String[] args) {
int[] myarr = {12, 12, 12, 8, 15, 15};
//Boolean array to mark the elements,defaults false
boolean[] b = new boolean[myarr.length];
//Compare Consecutive values and mark them true if equal
for (int i = 1; i < myarr.length; i++) {
if (myarr[i - 1] == myarr[i]) {
b[i - 1] = b[i] = true;
}
}
int sum = 0;
//Add all the values in myarr with indices marked as equal
for (int i = 0; i < b.length; i++) {
if (b[i]) {
sum += myarr[i];
}
}
System.out.println(sum);
}
}
Output:
66
Explanation:
12+12+12+15+15
Is there a better/cleaner way to compare values in array and add only values if they are equal, without using utility methods?
You could keep a running count of duplicate items and add them to your sum when the run ends.
int[] myarr = {12, 12, 12, 8, 15, 15};
// assumes > 0 length
int count = 1;
int sum = 0;
for (int i = 1; i < myarr.length; i++) {
if (myarr[i] == myarr[i - 1]) {
count++;
} else {
if (count > 1) {
sum += count * myarr[i - 1];
}
count = 1;
}
}
// handle if last elements are duplicates
if (count > 1) {
sum += count * myarr[myarr.length - 1];
}
System.out.println(sum);
You can solve this with linear efficiency. This program is a little bit cleaner and works in all conditions, checking all the edge cases. It results in the correct answer of 66 for your problem. It loops through the array, and checks if each element is consecutive (same as previous element). If so, it adds the element's value onto the sum. Edge cases need to be included to account for the starting elements of each consecutive block, which have to be added to the sum as well.
private static int consecutiveCompare(int[] array)
{
int sum = 0;
for (int i = 1; i < array.length; i++)
{
if (array[i] == array[i-1])
{
if (i == 1)
{
sum += array[i];
}
else if (array[i] != array[i-2])
{
sum += array[i];
}
sum += array[i];
}
}
return sum;
}
The following code will work:
public class LoopTest {
public static void main(String[] args) {
int[] myarr = {12, 12, 12, 8, 15, 15};
int sum = 0;
int occ = 1;
for (int i = 1; i < myarr.length; i++) {
if (myarr[i - 1] == myarr[i]) {
occ++;
} else {
if (occ > 1) {
sum += (occ * myarr[i - 1]);
}
occ = 1;
}
if (i == myarr.length - 1) {
if (occ > 1) {
sum += (occ * myarr[i - 1]);
}
}
}
System.out.println(sum);
}
}
Haven't tested all edge cases, here is what I have in my mind:
public class LoopTest {
public static void main(String[] args) {
int[] myarr = {1,1,1,2,2,3,3,4};
//Boolean array to mark the elements,defaults false
boolean[] b = new boolean[myarr.length];
//Last value tracker.
int lastVal = myarr[0];
//Count occurrences in a sequence.
int cntr = 1;
//Sum counter.
int sum = 0;
//Compare Consecutive values and mark them true if equal
for (int i = 1; i < myarr.length; i++) {
if (myarr[i] == lastVal) {
cntr++;
//If last sequence mathching.
if (i == myarr.length-1) {
sum += lastVal * cntr;
}
} else {
if (cntr > 1) {
sum += lastVal * cntr;
//Reset counter.
cntr = 1;
}
lastVal = myarr[i];
}
}
System.out.println(sum);
}
}
I have two classes Main and Object. I need to sort the objects in array in ascending order according to its value. I return -1, 1, and 0 from compareTo and I need to run a for loop accordingly to sort my array. I don't want to use Arrays.sort, I need to do it manually. The sorting part n the Main class does not work. Any help could be useful. Thank you.
public class Main {
public static void main(String[] args) {
Object[] arr = new Object[6];
arr[0] = new Object(2);
arr[1] = new Object(5);
arr[2] = new Object(3);
arr[3] = new Object(1);
arr[4] = new Object(6);
arr[5] = new Object(4);
System.out.println("List of instances");
for (int i = 0; i < 5; i++) {
System.out.println(arr[i].getValue());
}
System.out.println();
Object tempVar;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < 5; j++) {
int result = arr[i].compareTo(arr[i]);
if (result == -1) {
tempVar = arr[j + 1];
arr[j + 1] = arr[i];
arr[i] = tempVar;
}
}
}
System.out.println("List of sorted instances");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i].getValue());
}
}
}
public class Object implements Comparable<Object> {
private int value;
public Object(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
#Override
public int compareTo(Object o) {
int result = 0;
if (this.value > o.getValue()) {
result = 1;
} else if (this.value < o.getValue()) {
result = -1;
} else if (this.value == o.getValue()) {
result = 0;
}
return result;
}
}
If you want to loop over all elements of a collection, then don't use a fixed value like the 5 here:
System.out.println("List of instances");
for (int i = 0; i < 5; i++) {
Use arr.length instead.
This also applies to this line:
for (int j = 0; j < 5; j++) {
5 might be right, since the array length is 6 and you want to terminate before the last index, but this code will break if you use a larger array. Use arr.length - 1 instead of 5.
This line compares an array element with itself:
int result = arr[i].compareTo(arr[i]);
Therefore result will always be 0. Change it to either:
int result = arr[i].compareTo(arr[j]);
or:
int result = arr[j].compareTo(arr[i]);
Try both approaches to see the difference between them.
In your fix above, you're comparing the elements on index i and j. Therefore you should change this code:
if (result == -1) {
tempVar = arr[j + 1];
arr[j + 1] = arr[i];
arr[i] = tempVar;
}
to use the correct index of j:
if (result == -1) {
tempVar = arr[j];
arr[j] = arr[i];
arr[i] = tempVar;
}
Your current code compares the elements of i and j (well, not j due to the bug, but you meant that), but your swapping different elements due to the different index j+1.
The following is NOT a homework problem, it's just a set of problems that I've been working through for practice and I was wondering if anybody else could figure it out:
http://codingbat.com/prob/p159339
Return an array that contains exactly the same numbers as the given array, but rearranged so that every 3 is immediately followed by a 4. Do not move the 3's, but every other number may move. The array contains the same number of 3's and 4's, every 3 has a number after it that is not a 3 or 4, and a 3 appears in the array before any 4.
*SOLVED - here is my working code:
public int[] fix34(int...nums)
{
int[] returnArray = new int[nums.length];
//ASSIGN ARRAY
//We know that all 3's can't be moved, and after every 3 there
//will automatically be a 4
for(int i = 0; i<nums.length; i++)
{
if(nums[i] == 3)
{
returnArray[i] = 3;
returnArray[i+1] = 4;
}
}
//REBUILD ARRAY - UNMOVED INDEXES
//If a value was not moved/affected by the above, it will get placed into the array
//in the same position
for (int i = 0; i < nums.length; i++)
{
if (returnArray[i] != 3 && returnArray[i] != 4 && nums[i] != 3 && nums[i] != 4)
{
returnArray[i] = nums[i];
}
}
//REBUILD ARRAY - MOVED INDEXES
//changed values = 0 in returnArray, as a result, any time we hit a 0 we
//can simply assign the value that was in the 4's place in the nums array
OuterLoop: for (int i = 0; i < nums.length; i++)
{
if (returnArray[i] == 0)
{
for (int n = 0; n < returnArray.length; n++)
{
if (returnArray[n] == 4)
{
returnArray[i] = nums[n];
continue OuterLoop;
}
}
}
}
return returnArray;
}
I don't know java, but maybe I can help anyway. i dont want to give you the solution, but think of it like this:
you can move every number that isn't a 3. that's our only limit. that being said:
the only spots you need to change are the spots following 3s....so....every time you loop through, your program should be aware if it finds a spot after a 3 that isn't a 4....
it should also be aware if it finds any 4s not preceded by a 3......
during each loop, once it's found the location of each of those two things, you should know what to do.
Initialize all the variables
for(int i = 0; i<n-1; i++)
{
if(arr[i] == 3)
{
if(arr[i+1] == 4)
continue;
else
{
temp = 0;
while(arr[temp] != 4)
temp++;
//Write your own code here
}
//Complete the code
}
I have NOT provided the entire code. Try completing it as you said it was for your practice.
public int[] fix34(int[] nums) {
int[] arr = new int[nums.length];
int index = 0;
int tempVal= 0,j=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==3){
arr[i] = nums[i];
index=i+1;
tempVal = nums[i+1];
j=index;
while(j<nums.length){
if(j<nums.length && nums[j]==4){
//System.out.println(j+"\t="+nums[j]);
nums[j]=tempVal;
nums[index] = 4;
break;
}
j++;
}
tempVal=0;
index=0;
}else{
arr[i] = nums[i];
}
}
index =0;
for(int i=0;i<nums.length;i++){
if(nums[i]==3 && nums[i+1]==4){
i+=1;
}else if(nums[i]==4){
index = i;
j=index;
while(j<nums.length){
if(nums[j]==3 && nums[j+1]!=4){
arr[index] = nums[j+1];
arr[j+1] = 4;
}
j++;
}
}
}
return arr;
}
Here's mine: A little overkill, but is always right, anyways i make 2 additional arrays and I make 2 passes in the loop putting the correct elements in the correct places. See Logic Below.
public int[] fix34(int[] nums) {
int index1 = 0;
int index2 = 0;
int index3 = 0;
int[] only4 = fours(nums); //holds all 4's in nums
int[] misc = new int[count4(nums)]; //will hold numbers after 3
for(int a = 0; a < nums.length - 1; a++){
if(nums[a] == 3){
misc[index1] = nums[a + 1]; //get it for later use
index1++;
nums[a + 1] = only4[index2]; //now the number after 3 is a 4, from the
index2++; //only4 array
}
}
for(int b = 1; b < nums.length; b++){
if(nums[b] == 4 && nums[b - 1] != 3){ //finds misplaced 4's
nums[b] = misc[index3]; //replaces lone 4's with the
index3++; //right hand side of each 3 original values.
}
}
return nums;
}
public int count4(int[] nums){
int cnt = 0;
for(int e : nums){
if(e == 4){
cnt++;
}
}
return cnt;
}
public int[] fours(int[] nums){
int index = 0;
int[] onlyFours = new int[count4(nums)]; //must set length
for(int e : nums){
if(e == 4){
onlyFours[index] = e;
index++;
}
}
return onlyFours;
}
I solved mine using two ArrayLists which contain the places of 3's and 4's.
I hope this helps.
public int[] fix34(int[] nums)
{
//Create a copy of nums to manipulate.
int[] ret = nums;
//Create two ArrayLists which carry corresponding places of 3 and 4;
ArrayList<Integer> threePositions = new ArrayList<Integer>();
ArrayList<Integer> fourPositions = new ArrayList<Integer>();
//Get the places of 3 and 4 and put them in the respective ArrayLists.
for (int i = 0; i < ret.length; i++)
{
if (ret[i] == 3)
{
threePositions.add(i);
}
if (ret[i] == 4)
{
fourPositions.add(i);
}
}
//Swap all ints right after the 3 with one of the 4s by using the referenced
//ArrayLists values.
for (int i = 0; i < threePositions.size(); i++)
{
int temp = ret[threePositions.get(i) + 1];
ret[threePositions.get(i) + 1] = ret[fourPositions.get(i)];
ret[fourPositions.get(i)] = temp;
}
//Return the ret array.
return ret;
}