Related
If given an array of 1's and 0's, what's good algorithm to show the minimum number of adjacent swaps needed to group all of the 1's together. The 1's don't need to be grouped at any specific place in the array. They just need to be grouped in whatever place provides for the minimum number of adjacent swaps.
For example, if the array looks like this...
1,0,0,1,1,0,1
...the minimum number of adjacent swaps would be 3, because you'd center on index 4 and do the following swaps:
Swap indices 0 and 1, resulting in:
0,1,0,1,1,0,1
Swap indices 1 and 2, resulting in:
0,0,1,1,1,0,1
Swap indices 5 and 6, resulting in:
0,0,1,1,1,1,0
Anyone have a good algorithm for finding the minimum number of adjacent swaps for any array of 1's and 0's?
UPDATED:
The algorithm determines center by just getting an array of all indices of 1's. The center of that array will always hold the center index. Much faster.
oneIndices = array of indices of all 1's in the input
middleOfOnesIndices = round(oneIndices.length/2)-1 // index to the center index
minimumSwaps = 0
foreach index i of oneIndices
minimumSwaps += aboluteValue(oneIndices[middleOfOneIndices]-oneIndices[i])-absoluteValue(middleOfOneIndices-i);
Here's a fiddle to see it in action:
https://jsfiddle.net/3pmwrk0d/6/
This was a fun one. Thanks for the question.
Hi, firstly I would like to suggest that the minimum number of adjacent swaps would be 2 for your given example instead of 3. As just swap index 0 with index 2. So 1 swap from left and 1 swap from right.
Here is my way to find minimum of swaps to bring the array in consecutive 1's form -
Step 1 : First find the centre index for maximum number of consecutive 1's
Step 2 : Parse the left side of array to swap it and count the number of swap in a efficient manner(Do not swap unnecessarily)
Step 3 : Do the same for the right side array
Step 4 : Plus the counts of both side.
Please have a look at my java program based on same strategy :
`public class MinimumSwap
{
//function to find consecutive number index
public static int[] getMaxConsecutiveIndex(List<Integer> array)
{
int desiredIndex = -1;
int count = 0;
int dupDesiredIndex = -1;
int dupCount = 0;
int i = 0;
while(i < array.size())
{
if(array.get(i) == 0)
{
//pass duplcateIndex value to desiredIndex if count is more
if(dupCount > count)
{
desiredIndex = dupDesiredIndex;
count = dupCount;
}
dupDesiredIndex = -1;
dupCount = 0;
}
else
{
if(dupDesiredIndex == -1)
{
dupDesiredIndex = i;
dupCount = 1;
}
else
{
dupCount++;
}
}
i++;
}
return new int[]{desiredIndex,count};
}
public static int swapCount(List<Integer> array,int startIndex, int endIndex, boolean side)
{
// side == false means 0 at the left
// side == true means 1 at the left
System.out.println("startIndex "+startIndex+" endIndex "+endIndex+" side "+side);
int swapCount = 0;
if(side == false)
{
while(startIndex <= endIndex)
{
if(array.get(endIndex) == 0) // swap from the end only if it is 0
{
//check for first 1 from left to swap
while(array.get(startIndex) == 0 && (startIndex != endIndex))
startIndex++;
if(array.get(startIndex) == 1)
{
// now swap
int temp = array.get(startIndex);
array.set(startIndex, array.get(endIndex));
array.set(endIndex,temp);
swapCount++;
endIndex--;
}
}
endIndex--;
}
}
else
{
while(startIndex <= endIndex)
{
if(array.get(startIndex) == 0) // swap from the starting only if it is 0
{
//check for first 1 from right to swap
while(array.get(endIndex) == 0 && (startIndex != endIndex))
endIndex--;
if(array.get(endIndex) == 1)
{
// now swap
int temp = array.get(startIndex);
array.set(startIndex, array.get(endIndex));
array.set(endIndex,temp);
swapCount++;
startIndex++;
}
}
startIndex++;
}
}
return swapCount;
}
public static void main(String...strings)
{
List<Integer> arr = new ArrayList<Integer>();
int temp[] = {0,1,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,1,0,1};
//int temp[] = {1,0,0,1,1,0,1};
for(int i=0; i<temp.length; i++)
arr.add(temp[i]);
int centerIndex = getMaxConsecutiveIndex(arr)[0];
int consequtivecount = getMaxConsecutiveIndex(arr)[1];
System.out.println("centerIndex "+centerIndex+" consequtivecount "+consequtivecount);
int swapCountLeft = swapCount(arr,0, centerIndex-1, false);
int swapCountRight = swapCount(arr,centerIndex+consequtivecount, arr.size()-1, true);
System.out.println("total swap count "+swapCountLeft+" :: "+swapCountRight);
System.out.println("array after swapping "+arr);
}
}
`
I am not very sure about performance. But as per my knowledge it should not be inefficient. If anyone finds any performance issue please do let me know :)
Approach :
This can be done by finding number of zeroes to the right side of every 1 and add them. In order to sort the array every one always has to perform a swap operation with every zero on its right side.
So the total number of swap operations for a particular 1 in array is the number of zeroes on its right hand side. Find the number of zeroes on right side for every one i.e. the number of swaps and add them all to obtain the total number of swaps.
// Java code to find minimum number of swaps to sort a binary array
class MinimumNumberOfSwapsNeeded {
static int findMinSwaps(int arr[], int n)
{
// Array to store count of zeroes
int noOfZeroes[] = new int[n];
int i, count = 0;
// Count number of zeroes
// on right side of every one.
noOfZeroes[n - 1] = 1 - arr[n - 1];
for (i = n - 2; i >= 0; i--)
{
noOfZeroes[i] = noOfZeroes[i + 1];
if (arr[i] == 0)
noOfZeroes[i]++;
}
// Count total number of swaps by adding number
// of zeroes on right side of every one.
for (i = 0; i < n; i++)
{
if (arr[i] == 1)
count += noOfZeroes[i];
}
return count;
}
// Driver Code
public static void main(String args[])
{
int ar[] = { 0, 0, 1, 0, 1, 0, 1, 1 };
System.out.println(findMinSwaps(ar, ar.length));
}
}
**
Grouping the array of 0's and 1's such that minimum swaps can be calculated in O(2*n) ~ O(n) complexity.**
package com.segregate.array;
import java.util.ArrayList;
import java.util.List;
public class ArraySegregation {
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>();
/*
*
* List -> low high [1 1 0 0 1 0] -> [ 000111] or [111000]
*
* 1 1 0 0 1 0 -> 000111
*/
arr.add(0);
arr.add(0);
arr.add(0);
arr.add(1);
arr.add(1);
arr.add(0);
arr.add(1);
arr.add(0);
arr.add(0);
List<Integer> arr1 = new ArrayList<>(arr);
int low = 0, high = arr.size() - 1;
int counter1 = 0, counter2 = 0;
// case for swaps such that all 0 in the left side.
while (low < high) {
switch (arr.get(low)) {
case 0:
while (arr.get(low) == 0)
low++;
break;
case 1:
while (arr.get(high) == 1)
high--;
swap(low, high, arr);
counter1++;
high--;
low++;
break;
}
}
// case for swaps such that all 0 in the right side.
/*
* [1 1 0 0 1 0] -> 11 1 0 0 0
*
*
*/
low=0;high = arr1.size() - 1;
while (low < high) {
switch (arr1.get(low)) {
case 0:
while (arr1.get(high) == 0)
high--;
swap(low, high, arr1);
counter2++;
high--;
low++;
break;
case 1:
while (arr1.get(low) == 1)
low++;
break;
}
}
int count = (counter1 > counter2) ? counter2 : counter1;
System.out.println(count);
}
private static void swap(int low, int high, List<Integer> arr) {
int temp1 = 0;
temp1 = arr.get(low);// 1
arr.remove(low);
arr.add(low, arr.get(high-1));
arr.remove(high-1);
arr.add(high, temp1);
}
}
Here is a simple, but not very clever algorithm that will perform an exhaustive search for any input in the range [0, 255].
Input:
binary string
Output:
optimal number of steps
number of optimal solutions
one detailed example
var transition = [],
isSolution = [];
function init() {
var msk = [ 3, 6, 12, 24, 48, 96, 192 ],
i, j, n, x, cnt, lsb, msb, sz = [];
for(i = 0; i < 0x100; i++) {
for(n = cnt = msb = 0, lsb = 8; n < 8; n++) {
if(i & (1 << n)) {
cnt++;
lsb = Math.min(lsb, n);
msb = Math.max(msb, n);
}
}
sz[i] = msb - lsb;
isSolution[i] = (sz[i] == cnt - 1);
}
for(i = 0; i < 0x100; i++) {
for(j = 0, transition[i] = []; j < 0x100; j++) {
x = i ^ j;
if(msk.indexOf(x) != -1 && (x & i) != x && (x & j) != x && sz[j] <= sz[i]) {
transition[i].push(j);
}
}
}
}
function solve() {
var x = parseInt(document.getElementById('bin').value, 2),
path = [ x ],
list = [],
i, min, sol = [], res = [];
recurse(x, path, list);
for(i in list) {
if(min === undefined || list[i].length <= min) {
min = list[i].length;
(sol[min] = (sol[min] || [])).push(list[i]);
}
}
console.log('Optimal length: ' + (min - 1) + ' step(s)');
console.log('Number of optimal solutions: ' + sol[min].length);
console.log('Example:');
for(i in sol[min][0]) {
res.push(('0000000' + sol[min][0][i].toString(2)).substr(-8, 8));
}
console.log(res.join(' -> '));
}
function recurse(x, path, list) {
if(isSolution[x]) {
list.push(path);
return;
}
for(i in transition[x]) {
if(path.indexOf(y = transition[x][i]) == -1) {
recurse(y, path.slice().concat(y), list);
}
}
}
init();
<input id="bin" maxlength="8" placeholder="enter binary string">
<button onclick="solve()">solve</button>
I've encountered a question online: find any increase sub-sequence with size 3 in an un-ordered array using O(n) time complexity. (just need to return one valid result)
For example:
1 2 0 3 ==> 1 2 3
2 4 7 8 ==> 2 4 7; 4 7 8; 2 4 8 (anyone of them is Okay)
This one is pretty relative to the longest increase sub-sequence. But it is also very specific: we just want size 3. I came out an O(N) solution which requires to scan the array twice.
The idea:
(1) For each element, find is there any one smaller than it on the left side, is there any one larger than it on the right side.
(2) We can compute a minimum pre-array and a maximum post-array as pre-processing. For example:
1 2 0 3 ==> minimum pre-array: none 1 1 0
1 2 0 3 ==> maximum post-array: 3 3 3 None
I'm wondering is there any other solutions for this one?
Did you try looking a cs.stackexchange?
It has already been solved there: https://cs.stackexchange.com/questions/1071/is-there-an-algorithm-which-finds-sorted-subsequences-of-size-three-in-on-ti
One idea is to do something like longest increasing subsequence algorithm, and does it in one pass.
There are multiple solutions in that question I linked.
Here's the solution the question refers to (in JavaScript)
The comments http://www.geeksforgeeks.org/find-a-sorted-subsequence-of-size-3-in-linear-time/ have other alternative solutions.
function findIncSeq3(arr) {
var hi = Array(arr.length);
var lo = Array(arr.length);
hi[arr.length - 1] = lo[0] = null;
var tmp, i;
for (i = arr.length - 2, tmp = arr.length - 1; i >= 0; i--) {
if (arr[i] >= arr[tmp]) {
tmp = i;
hi[i] = null;
} else {
hi[i] = tmp;
}
}
for (i = 1, tmp = 0; i < arr.length; i++) {
if (arr[i] <= arr[tmp]) {
tmp = i;
lo[i] = null;
} else {
lo[i] = tmp;
}
}
for(i = 0; i < arr.length; i++) {
if(hi[i] !== null && lo[i] != null) {
return [arr[lo[i]], arr[i], arr[hi[i]]];
}
}
return null;
}
console.log("1,2,5", findIncSeq3([1, 2, 0, 5]));
console.log("null", findIncSeq3([5, 4, 3, 2, 1]));
console.log("2,3,9", findIncSeq3([10, 8, 6, 4, 2, 5, 3, 9]));
EDIT Here's a single iteration version.
function findIncSeq3(arr) {
var tmp = Array(arr.length);
for(var i = 0, s = arr.length - 1, lo = 0, hi = arr.length -1; i <= s; i++) {
if(s - i !== hi) {
if(arr[s - i] >= arr[hi]) {
hi = s - i;
} else if(tmp[s - i] !== undefined) {
return [arr[tmp[s - i]], arr[s - i], arr[hi]];
} else {
tmp[s - i] = hi;
}
}
if(i !== lo) {
if(arr[i] <= arr[lo]) {
lo = i;
} else if(tmp[i] !== undefined) {
return [arr[lo], arr[i], arr[tmp[i]]];
} else {
tmp[i] = lo;
}
}
}
return null;
}
I recently encountered a problem statement it says:
Given an array of 0s and 1s, find the position of 0 to be
replaced with 1 to get longest continuous sequence of 1s.
For example : Array- 1,1,0,0,1,0,1,1,1,0,1,1,1
Output - index 9
I tried a brute force approach replacing every encountered 0 with 1 and after each such replacement, i counted the largest continuous repetitive sequence of 1 and updated it every time.
Is there a better approach/algorithm to this problem?
There should be a one-pass solution to this. The overall idea is to count the ones and to add up the lengths for each zero as you go. Well, not each zero, just the last encountered one and the longest.
You need to keep track of two things:
The longest chain so far.
The previous zero value, along with the length of the preceding ones.
The process then goes as following:
Starting walking through the string until you encounter a zero. Keep track of the number of ones as you go.
When you hit the zero, remember the position of the zero along with the number of preceding 1s.
Count the 1s to the next zero.
Go back to the previous zero and add the new "ones" to the previous "ones". If this is longer than the longest chain, then replace the longest chain.
Remember this zero along with the preceding 1s.
Repeat until you have reached the end of the string.
At then end of the string, go back and add the length to the previous zero and replace the longest chain if appropriate.
You can imagine you have to maintain a set of 1 allowing only one 0 among them,
so
1) walk over the array,
2) if you are getting a 1,
check a flag if you are already in a set, if no,
then you start one and keep track of the start,
else if yes, you just update the end point of set
3) if you get a 0, then check if it can be included in the set,
(i.e. if only one 0 surrounded by 1 "lonely zero" )
if no, reset that flag which tells you you are in a set
else
is this first time ? (store this 0 pos, initialized to -1)
yes, then just update the zero position
else okk, then previous set, of one..zero..one gets finished here,
now the new set's first half i.e. first consecutive ones are the previous set's last portion,
so set the beginning of the set marker to last zero pos +1, update the zero position.
So when to get check if the current set is having highest length? See , we update the end point only in 2 -> else portion, so just check with max start, max end etc etc at that point and it should be enough
Here is my solution. It is clean, takes O(n) time and O(1) memory.
public class Q1 {
public Q1() {
}
public static void doit(int[] data) {
int state = 0;
int left, right, max_seq, max_i, last_zero;
left = right = 0;
max_seq = -1;
max_i = -1;
// initialization
right = data[0];
last_zero = (data[0]==0) ? 0 : -1;
for (int i = 1; i < data.length; i++) {
state = data[i - 1] * 10 + data[i];
switch (state) {
case 00: //reset run
left = right = 0;
last_zero = i;
break;
case 01: // beginning of a run
right++;
break;
case 10:// ending of a run
if(left+right+1>max_seq){
max_seq = left+right+1;
max_i = last_zero;
}
last_zero = i; //saving zero position
left = right; // assigning left
right = 0; // resetting right
break;
case 11: // always good
right++;
break;
}
}
//wrapping up
if(left+right+1>max_seq){
max_seq = left+right+1;
max_i = last_zero;
}
System.out.println("seq:" + max_seq + " index:" + max_i);
}
public static void main(String[] args) {
//Q1.doit(new int[] { 1,1,0,0,1,0,1,1,1,0,1,1,1 });
Q1.doit(new int[] { 1,1,0,0,1,0,1,1,1,0,1,1,1 });
}
}
Using Dynamic programming you can solve this code.
Time complexity is O(n) and space complexity is O(n).
public static int Flipindex(String mystring){
String[] arr = mystring.split(",");
String [] arrays= new String[arr.length];
for(int i=0;i<arr.length;i++){
arrays[i]="1";
}
int lastsum = 0;
int[] sumarray =new int[arr.length];
for(int i=0;i<arr.length;i++){
if(!arr[i].equals(arrays[i])){
++lastsum;
}
sumarray[i]=lastsum;
}
int [] consecsum = new int [sumarray[sumarray.length-1]+1];
for(int i: sumarray){
consecsum[i]+=1;
}
int maxconsecsum=0,startindex=0;
for(int i=0;i<consecsum.length-1;i++){
if((consecsum[i]+consecsum[i+1])>maxconsecsum){
maxconsecsum=(consecsum[i]+consecsum[i+1]);
startindex=i;
}
}
int flipindex=0;
for(int i=0;i<=startindex;i++){
flipindex+=consecsum[i];
}
return flipindex;
}
public static void main(String[] args) {
String s= "1,1,0,0,1,0,1,1,1,0,1,1,1";
System.out.println(Flipindex(s));
}
Playing around with console yielded me this, touch up and cover edge case then you are good to go
function getIndices(arr, val) {
var indexes = [], i = -1;
while ((i = arr.indexOf(val, i+1)) != -1){
indexes.push(i);
}
return indexes;
}
var a = [1,1,1,1,1,0,0,1,0,0,1,1,1,0,1,1,1,1,1,1,0];
var z = getIndices(a, 0);
z.unshift(0);
var longestchain = 0;
var target = 0;
for(var i=0;i<z.length;i++) {
if(i == 0) { //first element
longestchain = z[i] + z[i+1];
target = i;
} else if (i == z.length-1) { //last element
var lastDistance = Math.abs(z[i] - z[i-1]);
if(lastDistance > longestchain) {
longestchain = lastDistance;
target = i;
}
} else {
if(Math.abs(z[i] - z[i+1]) > 1) { //consecutive 0s
//look before and ahead
var distance = Math.abs(z[i-1] - z[i]) + Math.abs(z[i] - z[i+1]);
if(distance > longestchain) {
longestchain = distance;
target = i;
}
}
}
}
console.log("change this: " + z[target]);
I first search for zeroes in the array and stored the position in another array, so in my e.g. you will get something like this [0,5,6,8,9,13,20], then i just run a single loop to find the greatest distance from each element with their adjacent ones, and storing the distance in the "longestchain", everytime i find a longer chain, i take note of the index, in this case "13".
This C code implementation is based on the algorithm provided by #gordon-linoff above.
int maxOnesIndex1(bool arr[], int n)
{
int prevZeroPos = 0;
int oldOneCnt = 0;
int newOneCnt = 0;
int longestChainOfOnes = 0;
int longestChainPos = 0;
int i;
for(i=0; i<n; i++)
{
if(arr[i]!=0)
{
oldOneCnt++;
}
else // arr[i] == 0
{
prevZeroPos = i;
newOneCnt = 0;
// move by one to find next sequence of 1's
i++;
while(i<n && arr[i] == 1)
{
i++;
newOneCnt++;
}
if((oldOneCnt+newOneCnt) > longestChainOfOnes)
{
longestChainOfOnes = oldOneCnt+newOneCnt+1;
longestChainPos = prevZeroPos;
}
oldOneCnt = 0;
i = prevZeroPos;
}
}
if((oldOneCnt+newOneCnt) > longestChainOfOnes)
{
longestChainOfOnes = oldOneCnt+newOneCnt+1;
longestChainPos = prevZeroPos;
}
return longestChainPos;
}
Space Complexity - O(1)
Time Complexity - O(n)
A = map(int, raw_input().strip().split(' '))
left = 0 #Numbers of 1 on left of current index.
right = 0 #Number of 1 on right of current index.
longest = 0 #Longest sequence so far
index = 0
final_index = 0 # index of zero to get the longest sequence
i = 0
while i < A.__len__():
if A[i] == 0:
left = right
index = i
i += 1
right = 0
while i < A.__len__() and A[i] != 0:
right += 1
i += 1
if left + right + 1 > longest:
final_index = index
longest = left + right + 1
else:
right += 1
i += 1
print final_index, longest
Here is little different algorithm
public static int zeroIndexToGetMaxOnes(int[] binArray) {
int prevPrevIndex = -1, prevIndex = -1,currentLenght= -1, maxLenght = -1, requiredIndex = -1;
for (int currentIndex = 0; currentIndex < binArray.length; currentIndex++) {
if (binArray[currentIndex] == 0) {
if (prevPrevIndex != -1) {
currentLenght = currentIndex - (prevPrevIndex + 1);
if (currentLenght > maxLenght) {
maxLenght = currentLenght;
requiredIndex = prevIndex;
}
}
prevPrevIndex = prevIndex;
prevIndex = currentIndex;
} else {// case when last element is not zero, and input contains more than 3 zeros
if (prevIndex != -1 && prevPrevIndex != -1) {
currentLenght = currentIndex - (prevPrevIndex + 1);
if (currentLenght > maxLenght) {
maxLenght = currentLenght;
requiredIndex = prevIndex;
}
}
}
}
if (maxLenght == -1) { // less than three zeros
if (prevPrevIndex != -1) { // 2 zeros
if (prevIndex > (binArray.length - prevPrevIndex - 1)) {
requiredIndex = prevPrevIndex;
} else {
requiredIndex = prevIndex;
}
} else { // one zero
requiredIndex = prevIndex;
}
}
return requiredIndex;
}
Here is the unit tests
#Test
public void replace0ToGetMaxOnesTest() {
int[] binArray = {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1};
int index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(9));
binArray = new int[]{1,0,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(1));
binArray = new int[]{0,1,1,1,0,1};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{1,1,1,0,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(3));
binArray = new int[]{0,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{1,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{0,1,1,1,1};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(0));
}
def sol(arr):
zeros = [idx for idx, val in enumerate(arr) if val == 0]
if len(arr) == 0 or len(zeros) == 0:
return None
if len(arr) - 1 > zeros[-1]:
zeros.append(len(arr))
if len(zeros) == 1:
return zeros[0]
if len(zeros) == 2:
return max(zeros)
max_idx = None
diff = 0
for i in range(len(zeros) - 2):
# Calculating the difference of i+2 and i, since i+1 should be filled with 1 to find the max index
if zeros[i+2] - zeros[i] > diff:
diff = zeros[i + 2] - zeros[i] - 1
max_idx = zeros[i+1]
return max_idx
arr = [1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1]
print(sol(arr))
How to optimally divide an array into two subarrays so that sum of elements in both subarrays is same, otherwise give an error?
Example 1
Given the array
10, 20 , 30 , 5 , 40 , 50 , 40 , 15
It can be divided as
10, 20, 30, 5, 40
and
50, 40, 15
Each subarray sums up to 105.
Example 2
10, 20, 30, 5, 40, 50, 40, 10
The array cannot be divided into 2 arrays of an equal sum.
There exists a solution, which involves dynamic programming, that runs in O(n*TotalSum), where n is the number of elements in the array and TotalSum is their total sum.
The first part consists in calculating the set of all numbers that can be created by adding elements to the array.
For an array of size n, we will call this T(n),
T(n) = T(n-1) UNION { Array[n]+k | k is in T(n-1) }
(The proof of correctness is by induction, as in most cases of recursive functions.)
Also, remember for each cell in the dynamic matrix, the elements that were added in order to create it.
Simple complexity analysis will show that this is done in O(n*TotalSum).
After calculating T(n), search the set for an element exactly the size of TotalSum / 2.
If such an item exists, then the elements that created it, added together, equal TotalSum / 2, and the elements that were not part of its creation also equal TotalSum / 2 (TotalSum - TotalSum / 2 = TotalSum / 2).
This is a pseudo-polynomial solution. AFAIK, this problem is not known to be in P.
This is called partition problem. There are optimal solutions for some special cases. However, in general, it is an NP-complete problem.
In its common variant, this problem imposes 2 constraints and it can be done in an easier way.
If the partition can only be done somewhere along the length of the array (we do not consider elements out of order)
There are no negative numbers.
The algorithm that then works could be:
Have 2 variables, leftSum and rightSum
Start incrementing leftSum from the left, and rightSum from the right of the array.
Try to correct any imbalance in it.
The following code does the above:
public boolean canBalance(int[] nums) {
int leftSum = 0, rightSum = 0, i, j;
if(nums.length == 1)
return false;
for(i=0, j=nums.length-1; i<=j ;){
if(leftSum <= rightSum){
leftSum+=nums[i];
i++;
}else{
rightSum+=nums[j];
j--;
}
}
return (rightSum == leftSum);
}
The output:
canBalance({1, 1, 1, 2, 1}) → true OK
canBalance({2, 1, 1, 2, 1}) → false OK
canBalance({10, 10}) → true OK
canBalance({1, 1, 1, 1, 4}) → true OK
canBalance({2, 1, 1, 1, 4}) → false OK
canBalance({2, 3, 4, 1, 2}) → false OK
canBalance({1, 2, 3, 1, 0, 2, 3}) → true OK
canBalance({1, 2, 3, 1, 0, 1, 3}) → false OK
canBalance({1}) → false OK
canBalance({1, 1, 1, 2, 1}) → true OK
Ofcourse, if the elements can be combined out-of-order, it does turn into the partition problem with all its complexity.
a=[int(g) for g in input().split()] #for taking the array as input in a
single line
leftsum=0
n=len(a)
for i in range(n):
leftsum+=a[i] #calculates the sum of first subarray
rightsum=0
for j in range(i+1):
rightsum+=a[j] #calculates the sum of other subarray
if leftsum==rightsum:
pos=i+1 #if the sum of subarrays are equal,
break set position where the condition
gets satisfied and exit the loop
else:
pos=-1 #if the sum of subarrays is not
equal, set position to -1
if pos=-1 or pos=n:
print('It is not possible.')
else: #printing the sub arrays`
for k in range(n):
if pos=k:
print('')
print(str(a[k]),end='')
This Problem says that if an array can have two subarrays with their sum of elements as same.
So a boolean value should be returned.
I have found an efficient algorithm :
Algo: Procedure
Step 1: Take an empty array as a container , sort the initial array and keep in the empty one.
Step 2: now take two dynamically allocatable arrays and take out highest and 2nd highest from the auxilliary array and keep it in the two subarrays respectively , and delete from the auxiliary array.
Step 3: Compare the sum of elements in the subarrays , the smaller sum one will have chance to fetch highest remaining element in the array and then delete from the container.
Step 4: Loop thru Step 3 until the container is empty.
Step 5: Compare the sum of two subarrays , if they are same return true else false.
// The complexity with this problem is that there may be many combinations possible but this algo has one unique way .
Tried a different solution . other than Wiki solutions (Partition Problem).
static void subSet(int array[]) {
System.out.println("Input elements :" + Arrays.toString(array));
int sum = 0;
for (int element : array) {
sum = sum + element;
}
if (sum % 2 == 1) {
System.out.println("Invalid Pair");
return;
}
Arrays.sort(array);
System.out.println("Sorted elements :" + Arrays.toString(array));
int subSum = sum / 2;
int[] subSet = new int[array.length];
int tmpSum = 0;
boolean isFastpath = true;
int lastStopIndex = 0;
for (int j = array.length - 1; j >= 0; j--) {
tmpSum = tmpSum + array[j];
if (tmpSum == subSum) { // if Match found
if (isFastpath) { // if no skip required and straight forward
// method
System.out.println("Found SubSets 0..." + (j - 1) + " and "
+ j + "..." + (array.length - 1));
} else {
subSet[j] = array[j];
array[j] = 0;
System.out.println("Found..");
System.out.println("Set 1" + Arrays.toString(subSet));
System.out.println("Set 2" + Arrays.toString(array));
}
return;
} else {
// Either the tmpSum greater than subSum or less .
// if less , just look for next item
if (tmpSum < subSum && ((subSum - tmpSum) >= array[0])) {
if (lastStopIndex > j && subSet[lastStopIndex] == 0) {
subSet[lastStopIndex] = array[lastStopIndex];
array[lastStopIndex] = 0;
}
lastStopIndex = j;
continue;
}
isFastpath = false;
if (subSet[lastStopIndex] == 0) {
subSet[lastStopIndex] = array[lastStopIndex];
array[lastStopIndex] = 0;
}
tmpSum = tmpSum - array[j];
}
}
}
I have tested. ( It works well with positive number greater than 0) please let me know if any one face issue.
This is a recursive solution to the problem, one non recursive solution could use a helper method to get the sum of indexes 0 to a current index in a for loop and another one could get the sum of all the elements from the same current index to the end, which works. Now if you wanted to get the elements into an array and compare the sum, first find the point (index) which marks the spilt where both side's sum are equal, then get a list and add the values before that index and another list to go after that index.
Here's mine (recursion), which only determines if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side. Worry about indexOutOfBounds, which can easily happen in recursion, a slight mistake could prove fatal and yield a lot of exceptions and errors.
public boolean canBalance(int[] nums) {
return (nums.length <= 1) ? false : canBalanceRecur(nums, 0);
}
public boolean canBalanceRecur(int[] nums, int index){ //recursive version
if(index == nums.length - 1 && recurSumBeforeIndex(nums, 0, index)
!= sumAfterIndex(nums, index)){ //if we get here and its still bad
return false;
}
if(recurSumBeforeIndex(nums, 0, index + 1) == sumAfterIndex(nums, index + 1)){
return true;
}
return canBalanceRecur(nums, index + 1); //move the index up
}
public int recurSumBeforeIndex(int[] nums, int start, int index){
return (start == index - 1 && start < nums.length)
? nums[start]
: nums[start] + recurSumBeforeIndex(nums, start + 1, index);
}
public int sumAfterIndex(int[] nums, int startIndex){
return (startIndex == nums.length - 1)
? nums[nums.length - 1]
: nums[startIndex] + sumAfterIndex(nums, startIndex + 1);
}
Found solution here
package sort;
import java.util.ArrayList;
import java.util.List;
public class ArraySumSplit {
public static void main (String[] args) throws Exception {
int arr[] = {1 , 2 , 3 , 4 , 5 , 5, 1, 1, 3, 2, 1};
split(arr);
}
static void split(int[] array) throws Exception {
int sum = 0;
for(int n : array) sum += n;
if(sum % 2 == 1) throw new Exception(); //impossible to split evenly
List<Integer> firstPart = new ArrayList<Integer>();
List<Integer> secondPart = new ArrayList<Integer>();
if(!dfs(0, sum / 2, array, firstPart, secondPart)) throw new Exception(); // impossible to split evenly;
//firstPart and secondPart have the grouped elements, print or return them if necessary.
System.out.print(firstPart.toString());
int sum1 = 0;
for (Integer val : firstPart) {
sum1 += val;
}
System.out.println(" = " + sum1);
System.out.print(secondPart.toString());
int sum2 = 0;
for (Integer val : secondPart) {
sum2 += val;
}
System.out.println(" = " + sum2);
}
static boolean dfs(int i, int limit, int[] array, List<Integer> firstPart, List<Integer> secondPart) {
if( limit == 0) {
for(int j = i; j < array.length; j++) {
secondPart.add(array[j]);
}
return true;
}
if(limit < 0 || i == array.length) {
return false;
}
firstPart.add(array[i]);
if(dfs(i + 1, limit - array[i], array, firstPart, secondPart)) return true;
firstPart.remove(firstPart.size() - 1);
secondPart.add(array[i]);
if(dfs(i + 1, limit, array, firstPart, secondPart)) return true;
secondPart.remove(secondPart.size() - 1);
return false;
}
}
def listSegmentation(theList):
newList = [[],[]]
print(theList)
wt1 = 0
wt2 = 0
dWt = 0
for idx in range(len(theList)):
wt = theList[idx]
if (wt > (wt1 + wt2) and wt1 > 0 and wt2 > 0):
newList[0] = newList[0] + newList[1]
newList[1] = []
newList[1].append(wt)
wt1 += wt2
wt2 = wt
elif ((wt2 + wt) >= (wt1 + wt)):
wt1 += wt
newList[0].append(wt)
elif ((wt2 + wt) < (wt1 + wt)):
wt2 += wt
newList[1].append(wt)
#Balancing
if(wt1 > wt2):
wtDiff = sum(newList[0]) - sum(newList[1])
ls1 = list(filter(lambda x: x <= wtDiff, newList[0]))
ls2 = list(filter(lambda x: x <= (wtDiff/2) , newList[1]))
while len(ls1) > 0 or len(ls2) > 0:
if len(ls1) > 0:
elDif1 = max(ls1)
newList[0].remove(elDif1)
newList[1].append(elDif1)
if len(ls2) > 0:
elDif2 = max(ls2)
newList[0].append(elDif2)
newList[1].remove(elDif2)
wtDiff = sum(newList[0]) - sum(newList[1])
ls1 = list(filter(lambda x: x <= wtDiff, newList[0]))
ls2 = list(filter(lambda x: x <= (wtDiff/2) , newList[1]))
if(wt2 > wt1):
wtDiff = sum(newList[1]) - sum(newList[0])
ls2 = list(filter(lambda x: x <= wtDiff, newList[1]))
ls1 = list(filter(lambda x: x <= (wtDiff/2) , newList[0]))
while len(ls1) > 0 or len(ls2) > 0:
if len(ls1) > 0:
elDif1 = max(ls1)
newList[0].remove(elDif1)
newList[1].append(elDif1)
if len(ls2) > 0:
elDif2 = max(ls2)
newList[0].append(elDif2)
newList[1].remove(elDif2)
wtDiff = sum(newList[1]) - sum(newList[0])
ls2 = list(filter(lambda x: x <= wtDiff, newList[1]))
ls1 = list(filter(lambda x: x <= (wtDiff/2) , newList[0]))
print(ls1, ls2)
print(sum(newList[0]),sum(newList[1]))
return newList
#Test cases
lst1 = [4,9,8,3,11,6,13,7,2,25,28,60,19,196]
lst2 = [7,16,5,11,4,9,15,2,1,13]
lst3 = [8,17,14,9,3,5,19,11,4,6,2]
print(listSegmentation(lst1))
print(listSegmentation(lst2))
print(listSegmentation(lst3))
This Python3 function will split and balance a list of numbers to two separate lists equal in sum, if the sum is even.
Python3 solution:
def can_partition(a):
mylist1 = []
mylist2 = []
sum1 = 0
sum2 = 0
for items in a:
# Take total and divide by 2.
total = sum(a)
if total % 2 == 0:
half = total//2
else:
return("Exiting, sum has fractions, total %s half %s" % (total, total/2))
mylist1.append(items)
print('Total is %s and half is %s' %(total, total/2))
for i in a:
sum1 = sum(mylist1)
sum2 = sum(mylist2)
if sum2 < half:
mypop = mylist1.pop(0)
mylist2.append(mypop)
# Function to swtich numbers between the lists if sums are uneven.
def switchNumbers(list1, list2,switch_diff):
for val in list1:
if val == switch_diff:
val_index = list1.index(val)
new_pop = list1.pop(val_index)
list2.append(new_pop)
#Count so while do not get out of hand
count = len(a)
while count != 0:
sum1 = sum(mylist1)
sum2 = sum(mylist2)
if sum1 > sum2:
diff = sum1 -half
switchNumbers(mylist1, mylist2, diff)
count -= 1
elif sum2 > sum1:
diff = sum2 - half
switchNumbers(mylist2, mylist1, diff)
count -= 1
else:
if sum1 == sum2:
print('Values of half, sum1, sum2 are:',half, sum1,sum2)
break
count -= 1
return (mylist1, mylist2)
b = [ 2, 3, 4, 2, 3, 1, 2, 5, 4, 4, 2, 2, 3, 3, 2 ]
can_partition(b)
Output:
Total is 42 total, half is 21.0
Values of half, sum1 & sum2 are : 21 21 21
([4, 4, 2, 2, 3, 3, 2, 1], [2, 3, 4, 2, 3, 2, 5])
A non optimal solution in python,
from itertools import permutations
def get_splitted_array(a):
for perm in permutations(a):
l1 = len(perm)
for i in range(1, l1):
if sum(perm[0:i]) == sum(perm[i:l1]):
return perm[0:i], perm[i:l1]
>>> a = [6,1,3,8]
>>> get_splitted_array(a)
((6, 3), (1, 8))
>>> a = [5,9,20,1,5]
>>>
>>> get_splitted_array(a)
((5, 9, 1, 5), (20,))
>>>
Its O(n) time and O(n) space
def equal_subarr(arr):
n=len(arr)
post_sum = [0] * (n- 1) + [arr[-1]]
for i in range(n - 2, -1, -1):
post_sum[i] = arr[i] + post_sum[i + 1]
prefix_sum = [arr[0]] + [0] * (n - 1)
for i in range(1, n):
prefix_sum[i] = prefix_sum[i - 1] + arr[i]
for i in range(n - 1):
if prefix_sum[i] == post_sum[i + 1]:
return [arr[:i+1],arr[i+1:]]
return -1
arr=[10, 20 , 30 , 5 , 40 , 50 , 40 , 15]
print(equal_subarr(arr))
>>> [[10, 20, 30, 5, 40], [50, 40, 15]]
arr=[10, 20, 30, 5, 40, 50, 40, 10]
print(equal_subarr(arr))
>>> -1
First, if the elements are integers, check that the total is evenly divisible by two- if it isn't success isn't possible.
I would set up the problem as a binary tree, with level 0 deciding which set element 0 goes into, level 1 deciding which set element 1 goes into, etc. At any time if the sum of one set is half the total, you're done- success. At any time if the sum of one set is more than half the total, that sub-tree is a failure and you have to back up. At that point it is a tree traversal problem.
public class Problem1 {
public static void main(String[] args) throws IOException{
Scanner scanner=new Scanner(System.in);
ArrayList<Integer> array=new ArrayList<Integer>();
int cases;
System.out.println("Enter the test cases");
cases=scanner.nextInt();
for(int i=0;i<cases;i++){
int size;
size=scanner.nextInt();
System.out.println("Enter the Initial array size : ");
for(int j=0;j<size;j++){
System.out.println("Enter elements in the array");
int element;
element=scanner.nextInt();
array.add(element);
}
}
if(validate(array)){
System.out.println("Array can be Partitioned");}
else{
System.out.println("Error");}
}
public static boolean validate(ArrayList<Integer> array){
boolean flag=false;
Collections.sort(array);
System.out.println(array);
int index=array.size();
ArrayList<Integer> sub1=new ArrayList<Integer>();
ArrayList<Integer> sub2=new ArrayList<Integer>();
sub1.add(array.get(index-1));
array.remove(index-1);
index=array.size();
sub2.add(array.get(index-1));
array.remove(index-1);
while(!array.isEmpty()){
if(compareSum(sub1,sub2)){
index=array.size();
sub2.add(array.get(index-1));
array.remove(index-1);
}
else{
index=array.size();
sub1.add(array.get(index-1));
array.remove(index-1);
}
}
if(sumOfArray(sub1).equals(sumOfArray(sub2)))
flag=true;
else
flag=false;
return flag;
}
public static Integer sumOfArray(ArrayList<Integer> array){
Iterator<Integer> it=array.iterator();
Integer sum=0;
while(it.hasNext()){
sum +=it.next();
}
return sum;
}
public static boolean compareSum(ArrayList<Integer> sub1,ArrayList<Integer> sub2){
boolean flag=false;
int sum1=sumOfArray(sub1);
int sum2=sumOfArray(sub2);
if(sum1>sum2)
flag=true;
else
flag=false;
return flag;
}
}
// The Greedy approach //
I was asked this question in an interview, and I gave below simple solution, as I had NOT seen this problem in any websiteS earlier.
Lets say Array A = {45,10,10,10,10,5}
Then, the split will be at index = 1 (0-based index) so that we have two equal sum set {45} and {10,10,10,10,5}
int leftSum = A[0], rightSum = A[A.length - 1];
int currentLeftIndex = 0; currentRightIndex = A.length - 1
/*
Move the two index pointers towards mid of the array untill currentRightIndex != currentLeftIndex. Increase leftIndex if sum of left elements is still less than or equal to sum of elements in right of 'rightIndex'.At the end,check if leftSum == rightSum. If true, we got the index as currentLeftIndex+1(or simply currentRightIndex, as currentRightIndex will be equal to currentLeftIndex+1 in this case).
*/
while (currentLeftIndex < currentRightIndex)
{
if ( currentLeftIndex+1 != currentRightIndex && (leftSum + A[currentLeftIndex + 1) <=currentRightSum )
{
currentLeftIndex ++;
leftSum = leftSum + A[currentLeftIndex];
}
if ( currentRightIndex - 1 != currentLeftIndex && (rightSum + A[currentRightIndex - 1] <= currentLeftSum)
{
currentRightIndex --;
rightSum = rightSum + A[currentRightIndex];
}
}
if (CurrentLeftIndex == currentRightIndex - 1 && leftSum == rightSum)
PRINT("got split point at index "+currentRightIndex);
#Gal Subset-Sum problem is NP-Complete and has a O(n*TotalSum) pseudo-polynomial Dynamic Programming algorithm. But this problem is not NP-Complete. This is a special case and in fact this can be solved in linear time.
Here we are looking for an index where we can split the array into two parts with same sum.
Check following code.
Analysis: O(n), as the algorithm only iterates through the array and does not use TotalSum.
public class EqualSumSplit {
public static int solution( int[] A ) {
int[] B = new int[A.length];
int[] C = new int[A.length];
int sum = 0;
for (int i=0; i< A.length; i++) {
sum += A[i];
B[i] = sum;
// System.out.print(B[i]+" ");
}
// System.out.println();
sum = 0;
for (int i=A.length-1; i>=0; i--) {
sum += A[i];
C[i] = sum;
// System.out.print(C[i]+" ");
}
// System.out.println();
for (int i=0; i< A.length-1; i++) {
if (B[i] == C[i+1]) {
System.out.println(i+" "+B[i]);
return i;
}
}
return -1;
}
public static void main(String args[] ) {
int[] A = {-7, 1, 2, 3, -4, 3, 0};
int[] B = {10, 20 , 30 , 5 , 40 , 50 , 40 , 15};
solution(A);
solution(B);
}
}
Algorithm:
Step 1) Split the array into two
Step 2) If the sum is equal, split is complete
Step 3) Swap one element from array1 with array2, guided by the four rules:
IF the sum of elements in array1 is less than sum of elements in array2
Rule1:
Find a number in array1 that is smaller than a number in array2 in such a way that swapping of
these elements, do not increase the sum of array1 beyond the expected sum. If found, swap the
elements and return.
Rule2:
If Rule1 is not is not satisfied, Find a number in array1 that is bigger than a number in array2 in
such a way that the difference between any two numbers in array1 and array2 is not smaller than
the difference between these two numbers.
ELSE
Rule3:
Find a number in array1 that is bigger than a number in array2 in such a way that swapping these
elements, do not decrease the sum of array1 beyond the expected sum. If found, swap the elements and return.
Rule4:
If Rule3 is not is not satisfied, Find a number in array1 that is smaller than a number in array2 in
such a way that the difference between any two numbers in array1 and array2 is not smaller than
the difference between these two numbers.
Step 5) Go to Step2 until the swap results in an array with the same set of elements encountered already
Setp 6) If a repetition occurs, this array cannot be split into two halves with equal sum. The current set of arrays OR the set that was formed just before this repetition should be the best split of the array.
Note: The approach taken is to swap element from one array to another in such a way that the resultant sum is as close to the expected sum.
The java program is available at Java Code
Please try this and let me know if not working. Hope it will helps you.
static ArrayList<Integer> array = null;
public static void main(String[] args) throws IOException {
ArrayList<Integer> inputArray = getinputArray();
System.out.println("inputArray is " + inputArray);
Collections.sort(inputArray);
int totalSum = 0;
Iterator<Integer> inputArrayIterator = inputArray.iterator();
while (inputArrayIterator.hasNext()) {
totalSum = totalSum + inputArrayIterator.next();
}
if (totalSum % 2 != 0) {
System.out.println("Not Possible");
return;
}
int leftSum = inputArray.get(0);
int rightSum = inputArray.get(inputArray.size() - 1);
int currentLeftIndex = 0;
int currentRightIndex = inputArray.size() - 1;
while (leftSum <= (totalSum / 2)) {
if ((currentLeftIndex + 1 != currentRightIndex)
&& leftSum != (totalSum / 2)) {
currentLeftIndex++;
leftSum = leftSum + inputArray.get(currentLeftIndex);
} else
break;
}
if (leftSum == (totalSum / 2)) {
ArrayList<Integer> splitleft = new ArrayList<Integer>();
ArrayList<Integer> splitright = new ArrayList<Integer>();
for (int i = 0; i <= currentLeftIndex; i++) {
splitleft.add(inputArray.get(i));
}
for (int i = currentLeftIndex + 1; i < inputArray.size(); i++) {
splitright.add(inputArray.get(i));
}
System.out.println("splitleft is :" + splitleft);
System.out.println("splitright is :" + splitright);
}
else
System.out.println("Not possible");
}
public static ArrayList<Integer> getinputArray() {
Scanner scanner = new Scanner(System.in);
array = new ArrayList<Integer>();
int size;
System.out.println("Enter the Initial array size : ");
size = scanner.nextInt();
System.out.println("Enter elements in the array");
for (int j = 0; j < size; j++) {
int element;
element = scanner.nextInt();
array.add(element);
}
return array;
}
}
public boolean splitBetween(int[] x){
int sum=0;
int sum1=0;
if (x.length==1){
System.out.println("Not a valid value");
}
for (int i=0;i<x.length;i++){
sum=sum+x[i];
System.out.println(sum);
for (int j=i+1;j<x.length;j++){
sum1=sum1+x[j];
System.out.println("SUm1:"+sum1);
}
if(sum==sum1){
System.out.println("split possible");
System.out.println("Sum: " +sum +" Sum1:" + sum1);
return true;
}else{
System.out.println("Split not possible");
}
sum1=0;
}
return false;
}
package PACKAGE1;
import java.io.*;
import java.util.Arrays;
public class programToSplitAnArray {
public static void main(String args[]) throws NumberFormatException,
IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter the no. of elements to enter");
int n = Integer.parseInt(br.readLine());
int x[] = new int[n];
int half;
for (int i = 0; i < n; i++) {
x[i] = Integer.parseInt(br.readLine());
}
int sum = 0;
for (int i = 0; i < n; i++) {
sum = sum + x[i];
}
if (sum % 2 != 0) {
System.out.println("the sum is odd and cannot be divided");
System.out.println("The sum is " + sum);
}
else {
boolean div = false;
half = sum / 2;
int sum1 = 0;
for (int i = 0; i < n; i++) {
sum1 = sum1 + x[i];
if (sum1 == half) {
System.out.println("array can be divided");
div = true;
break;
}
}
if (div == true) {
int t = 0;
int[] array1 = new int[n];
int count = 0;
for (int i = 0; i < n; i++) {
t = t + x[i];
if (t <= half) {
array1[i] = x[i];
count++;
}
}
array1 = Arrays.copyOf(array1, count);
int array2[] = new int[n - count];
int k = 0;
for (int i = count; i < n; i++) {
array2[k] = x[i];
k++;
}
System.out.println("The first array is ");
for (int m : array1) {
System.out.println(m);
}
System.out.println("The second array is ");
for (int m : array2) {
System.out.println(m);
}
} else {
System.out.println("array cannot be divided");
}
}
}
}
A BAD greedy heuristic to solve this problem: try sorting the list from least to greatest, and split that list into two by having list1 = the odd elements, and list2 = the even elements.
very simple solution with recursion
public boolean splitArray(int[] nums){
return arrCheck(0, nums, 0);
}
public boolean arrCheck(int start, int[] nums, int tot){
if(start >= nums.length) return tot == 0;
if(arrCheck(start+1, nums, tot+nums[start])) return true;
if(arrCheck(start+1, nums, tot-nums[start])) return true;
return false;
}
https://github.com/ShubhamAgrahari/DRjj/blob/master/Subarray_Sum.java
package solution;
import java.util.Scanner;
public class Solution {
static int SplitPoint(int arr[], int n)
{
int leftSum = 0;
for (int i = 0 ; i < n ; i++)
leftSum += arr[i];
int rightSum = 0;
for (int i = n-1; i >= 0; i--)
{
rightSum += arr[i];
leftSum -= arr[i] ;
if (rightSum == leftSum)
return i ;
}
return -1;
}
static void output(int arr[], int n)
{
int s = SplitPoint(arr, n);
if (s == -1 || s == n )
{
System.out.println("Not Possible" );
return;
}
for (int i = 0; i < n; i++)
{
if(s == i)
System.out.println();
System.out.print(arr[i] + " ");
}
}
public static void main (String[] args) {
Scanner sc= new Scanner(System.in);
System.out.println("Enter Array Size");
int n = sc.nextInt();
int arr[]= new int[n];
for(int i=0;i<n;i++)
{
arr[i]=sc.nextInt();
}
output(arr, n);
} }
Is there an easy way of finding the neighbours (that is, the eight elements around an element) of an element in a two-dimensional array? Short of just subtracting and adding to the index in different combinations, like this:
array[i-1][i]
array[i-1][i-1]
array[i][i-1]
array[i+1][i]
... And so on.
(pseudo-code)
row_limit = count(array);
if(row_limit > 0){
column_limit = count(array[0]);
for(x = max(0, i-1); x <= min(i+1, row_limit); x++){
for(y = max(0, j-1); y <= min(j+1, column_limit); y++){
if(x != i || y != j){
print array[x][y];
}
}
}
}
Of course, that takes almost as many lines as the original hard-coded solution, but with this one you can extend the "neighborhood" as much as you can (2-3 or more cells away)
I think Ben is correct in his approach, though I might reorder it, to possibly improve locality.
array[i-1][j-1]
array[i-1][j]
array[i-1][j+1]
array[i][j-1]
array[i][j+1]
array[i+1][j-1]
array[i+1][j]
array[i+1][j+1]
One trick to avoid bounds checking issues, is to make the array dimensions 2 larger than needed. So, a little matrix like this
3 1 4
1 5 9
2 6 5
is actually implemented as
0 0 0 0 0
0 3 1 4 0
0 1 5 9 0
0 2 6 5 0
0 0 0 0 0
then while summing, I can subscript from 1 to 3 in both dimensions, and the array references above are guaranteed to be valid, and have no effect on the final sum.
I am assuming c, and zero based subscripts for the example
Here is a working Javascript example from #seb original pseudo code:
function findingNeighbors(myArray, i, j) {
var rowLimit = myArray.length-1;
var columnLimit = myArray[0].length-1;
for(var x = Math.max(0, i-1); x <= Math.min(i+1, rowLimit); x++) {
for(var y = Math.max(0, j-1); y <= Math.min(j+1, columnLimit); y++) {
if(x !== i || y !== j) {
console.log(myArray[x][y]);
}
}
}
}
an alternative to #SebaGR, if your language supports this:
var deltas = { {x=-1, y=-1}, {x=0, y=-1}, {x=1, y=-1},
{x=-1, y=0}, {x=1, y=0},
{x=-1, y=1}, {x=0, y=1}, {x=1, y=1} };
foreach (var delta in deltas)
{
if (x+delta.x < 0 || x + delta.x >= array.GetLength(0) ||
y+delta.y < 0 || y + delta.y >= array.GetLength(1))
continue;
Console.WriteLine("{0}", array[x + delta.x, y + delta.y]);
}
Slight advantage in readability, possible performance if you can statically allocate the deltas.
To print the neighbors of L[row][column]:
print(L[row-1][column-1], L[row-1][column], L[row-1][column+1])
print(L[row][column-1], L[row][column], L[row][column+1])
print(L[row+1][column-1], L[row+1][column], L[row+1][column+1])
That's probably the fastest/easiest way is to just print possible neighbors. Make sure to do index out of bound checking though.
Some languages might offer a shortcut way of doing this, but I don't know of any.
This is an implementation of #Seb's answer in python3+ that is concise and uses generators for max performance:
def neighbours(pos, matrix):
rows = len(matrix)
cols = len(matrix[0]) if rows else 0
for i in range(max(0, pos[0] - 1), min(rows, pos[0] + 2)):
for j in range(max(0, pos[1] - 1), min(cols, pos[1] + 2)):
if (i, j) != pos:
yield matrix[i][j]
Grid (vector 2D or one dimension... not the problem here)
X & Y, coordinate of your element (or just pass your vector element by ref...)
int neighbour(const Grid & g, const size_t & x, const size_t & y) {
for (int i = -1; i < 2; ++i)
for (int j = -1; j < 2; ++j)
if (x + i >= 0 && x + i < g.row && y + j >= 0 && y + j < g.col)
//Do some stuff
return 0;
}
// My approach in JS
let size = 10
//or some arbitrary number for the size of your grid.
const neighbors = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 0],
[1, 1]
]
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
neighbors.forEach(([x, y]) => {
const newI = i + x;
const newJ = j + y;
if (
newI >= 0 &&
newI < size &&
newJ >= 0 &&
newJ < size
) {
// you can access your grid neighbors here ----> grid[newI][newJ];
}
```
I've found this approach helpful because it defines all of the array coordinates as transformations of the existing i and j indexes in your for loops.
Here is a convenient method in Python:
def neighbors(array,pos):
n = []
string = "array[pos.y+%s][pos.x+%s]"
for i in range(-1,2):
for j in range(-1,2):
n.append(eval(string % (i,j)))
return n
Assuming pos is some 2D Point object and array is a 2D array.
Since in a matrix around an element there are only 8 elements, you can use array to store different index values.For e.g.,
int iarr[8] = {-1,-1,-1,0,0,+1,+1,+1};
int jarr[8] = {-1,0,+1,-1,+1,-1,0,+1};
for(int i = 0 ; i < 8 ; i++)
{
if(arr[x-iarr[i]][y-jarr[i]] == 1)
{
//statements
}
}
/* x and y are the position of elements from where you want to reach out its neighbour */
since both array contains just 8 values , then space might not be a problem.
The approach I usually take is described on the bottom of this blog:
https://royvanrijn.com/blog/2019/01/longest-path/
Instead of hardcoding the directions or having two nested loops I like to use a single integer loop for the 8 ‘directions’ and use (i % 3)-1 and (i / 3)-1; do check out the blog with images.
It doesn’t nest as deep and is easily written, not a lot of code needed!
JS sample :
function findingNeighbors(myArray, i, j){
return myArray.reduce(function(a, b, c){
if(Math.max(0, i-1) <= c && c <= Math.min(i+1, myArray.length-1)){
a = a.concat(
b.reduce(function(d, e, f){
if(f == j && c == i)
return d;
if(Math.max(0, j-1) <= f && f <= Math.min(j+1, myArray.length-1))
d.push(e)
return d;
},[])
);
}
return a;
},[]);
}
A lot depends on what your data is. For example, if your 2D array is a logical matrix, you could convert rows to integers and use bitwise operations to find the ones you want.
For a more general-purpose solution I think you're stuck with indexing, like SebaGR's solution.
Rows and Cols are total number of rows and cols
Define a CellIndex struct or class. Or you can just return the actual values instead of the indexes.
public List<CellIndex> GetNeighbors(int rowIndex, int colIndex)
{
var rowIndexes = (new int[] { rowIndex - 1, rowIndex, rowIndex + 1 }).Where(n => n >= 0 && n < Rows);
var colIndexes = (new int[] { colIndex - 1, colIndex, colIndex + 1 }).Where(n => n >= 0 && n < Cols);
return (from row in rowIndexes from col in colIndexes where row != rowIndex || col != colIndex select new CellIndex { Row = row, Col = col }).ToList();
}
private ArrayList<Element> getNeighbors(Element p) {
ArrayList<Element> n = new ArrayList<Element>();
for (int dr = -1; dr <= +1; dr++) {
for (int dc = -1; dc <= +1; dc++) {
int r = p.row + dr;
int c = p.col + dc;
if ((r >= 0) && (r < ROWS) && (c >= 0) && (c < COLS)) {
// skip p
if ((dr != 0) || (dc != 0))
n.add(new Element(r, c));
}
}
}
return n;
}
although nested for loops in list comprehensions is a bit ugly this is shorter:
def neighbours(m, i, j):
return [m[x][y] for x in [i-1,i,i+1] for y in [j-1,j,j+1] if x in range(0,len(m)) and y in range(0,len(m[x])) and (x,y) != (i,j)]
here is some code for C#:
public Cell[,] MeetNeigbours(Cell[,] Grid)
{
for (int X = 0; X < Grid.GetLength(0); X++)
{
for (int Y = 0; Y < Grid.GetLength(1); Y++)
{
int NeighbourCount = 0;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (CellExists(Grid, (X + i)), (Y + j) && (i != 0 && j != 0))
{
Grid[X, Y].Neighbours[NeighbourCount] = Grid[(X + i), (Y + j)];
}
if(!(i == 0 && j == 0))
{
NeighbourCount++;
}
}
}
}
}
return Grid;
}
public bool CellExists(Cell[,] Grid, int X, int Y)
{
bool returnValue = false;
if (X >= 0 && Y >= 0)
{
if (X < Grid.GetLength(0) && Y < Grid.GetLength(1))
{
returnValue = true;
}
}
return returnValue;
}
with the "Cell" class looking like this:
public class Cell
{
public Cell()
{
Neighbours = new Cell[8];
}
/// <summary>
/// 0 3 5
/// 1 X 6
/// 2 4 7
/// </summary>
public Cell[] Neighbours;
}
This was really helpful to me in a recent project, so here's #Seb 's pseudo-code implementation in swift. This is assuming that the two-dimensional array is square:
func adjacentIndexPaths(to indexPath: IndexPath) -> [IndexPath] {
var neighboringSquareIndexes: [IndexPath] = []
// gridSquareCount is the size of the 2D array. For example, in an 8 x 8 [[Array]], gridSquareCount is 8
let maxIndex = gridSquareCount - 1
var neighborRowIndex = max(0, indexPath.section - 1)
var neighborColumnIndex = max(0, indexPath.row - 1)
while neighborRowIndex <= min(indexPath.section + 1, maxIndex) {
while neighborColumnIndex <= min(indexPath.row + 1, maxIndex) {
if neighborRowIndex != indexPath.section || neighborColumnIndex != indexPath.row {
neighboringSquareIndexes.append(IndexPath(row: neighborColumnIndex, section: neighborRowIndex))
}
neighborColumnIndex += 1
}
neighborRowIndex += 1
neighborColumnIndex = max(0, indexPath.row - 1)
}
return neighboringSquareIndexes }
In javascript
let arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
function getNeighborsNumbersAtIthJth(i, j) {
let allPosibleIndexes = [
[i - 1, j],
[i, j - 1],
[i - 1, j - 1],
[i + 1, j],
[i, j + 1],
[i + 1, j + 1],
[i + 1, j - 1],
[i - 1, j + 1]
];
let allPosibleValues = []
allPosibleIndexes.forEach(([i, j]) => {
try {
allPosibleValues.push(arr[i][j])
} catch (err) {
}
})
return allPosibleValues.filter(v => v != undefined);
}
console.log(getNeighborsNumbersAtIthJth(1, 1));//[2, 4, 1, 8, 6, 9, 7, 3]
console.log(getNeighborsNumbersAtIthJth(0, 1));//[1, 5, 3, 6, 4]
console.log(getNeighborsNumbersAtIthJth(0, 0));//[4, 2, 5]
I use a directions array and run a loop to get appropriate directions. Something like this (code is in JS)
function getAdjacent(matrix, i, j, k) {
const directions = [
[i - 1, j - 1],
[i - 1, j],
[i - 1, j + 1],
[i, j - 1],
[i, j + 1],
[i + 1, j - 1],
[i + 1, j],
[i + 1, j + 1],
];
const [row, col] = directions[k];
// Check for last rows and columns
if (row < 0 || row >= matrix.length || col < 0 || col >= matrix[i].length) {
return undefined;
}
return matrix[row][col];
}
function run(){
const hello = 'hello';
const matrix = [
[1, 2, 1],
[2, 1, 1],
[1, 1, 1]
];
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
let sum = 0;
for (let k = 0; k < 8; k++) {
const res = getAdjacent(matrix, i, j, k);
console.log(i, j, k, res); // Do whatever you want here
}
}
}
}
run();
This example in Python might also shed some light:
from itertools import product
def neighbors(coord: tuple, grid=(10, 10), diagonal=True):
"""Retrieve all the neighbors of a coordinate in a fixed 2d grid (boundary).
:param diagonal: True if you also want the diagonal neighbors, False if not
:param coord: Tuple with x, y coordinate
:param grid: the boundary of the grid in layman's terms
:return: the adjacent coordinates
"""
width = grid[0] - 1
height = grid[1] - 1
retx, rety = coord
adjacent = []
nb = [x for x in product([-1, 0, 1], repeat=2) if x != (0, 0)]
if not diagonal:
nb = [x for x in nb if x not in product([-1, 1], repeat=2)]
for x, y in nb:
xx = retx + x
yy = rety + y
if xx < 0 or xx > width or yy < 0 or yy > height:
# not within its boundaries
continue
adjacent.append((xx, yy))
return adjacent
the first product line (nb = [x for x in product([-1, 0, 1], repeat=2) if x != (0, 0)]) will produce all the coordinates of its neibors including the diagonal ones. The (0,0) is removed because that is ourselves so not a neighbor :-)
[(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
If you do not want the diagonal neighbors you can tell it to remove those (product([-1, 1], repeat=2)) then the boundaries of the grid are checked and the resulting list of coordinates will be produced.
Ruby => Returns an array of neighbours.
array = [
[1, 2, 5, 6],
[8, 89, 44, 0],
[8, 7, 23, 0],
[6, 9, 3, 0]
]
def neighbours(array, (i , j))
[
[i, j - 1],
[i, j + 1],
[i - 1, j - 1],
[i - 1, j],
[i - 1, j + 1],
[i + 1, j - 1],
[i + 1, j],
[i + 1, j + 1],
].select { |h, w|
h.between?(0, array.length - 1) && w.between?(0, array.first.length - 1)
}.map do |row, col|
array[row][col]
end
end
array.each_with_index do |row, i|
row.each_with_index do |col, j|
p(array[i][j], neighbours(array, [i, j]))
end
end
I know this is an older question. However, I want to post a solution that I wrote based on Shubh Tripathi's answer
If we're looking for the same neighbors every time and want efficient bounds checking, there is a simple way to achieve this by just storing the indexes we want in an array without re-generating them in each iteration.
I wrote this for a simulation, where I wanted to check all directions surrounding an entity.
def get_surroundings(self, position):
"""
For a given grid location, it returns the surrounding 8x8 grid.
Indexed from the top left to the bottom right. (row-wise)
Args:
position (tuple): The position of the grid location.
Returns:
list: The surrounding 8x8 grid.
"""
# set the x and y coordinates
x = position[0]
y = position[1]
# list out the relative locations of the neighbors
surroundings = [
(-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1),
(1, -1), (1, 0), (1, 1)
]
return_list = []
# go through the relative neighbours list, and check if any of the
# bounds condition fail. if they do, append none.
for neighbour in surroundings:
if (
x + neighbour[0] < 0 or
x + neighbour[0] >= self.grid_size or
y + neighbour[1] < 0 or
y + neighbour[1] >= self.grid_size
):
return_list.append(None)
else:
return_list.append(self.grid[x + neighbour[0]][y + neighbour[1]])
self.grid is your 2x2 grid.