I am given 2 arrays, Input and Output Array. The goal is to transform the input array to output array by performing shifting of 1 value in a given step to its adjacent element. Eg: Input array is [0,0,8,0,0] and Output array is [2,0,4,0,2]. Here 1st step would be [0,1,7,0,0] and 2nd step would be [0,1,6,1,0] and so on.
What can be the algorithm to do this efficiently? I was thinking of performing BFS but then we have to do BFS from each element and this can be exponential. Can anyone suggest solution for this problem?
I think you can do this simply by scanning in each direction tracking the cumulative value (in that direction) in the current array and the desired output array and pushing values along ahead of you as necessary:
scan from the left looking for first cell where
cumulative value > cumulative value in desired output
while that holds move 1 from that cell to the next cell to the right
scan from the right looking for first cell where
cumulative value > cumulative value in desired output
while that holds move 1 from that cell to the next cell to the left
For your example the steps would be:
FWD:
[0,0,8,0,0]
[0,0,7,1,0]
[0,0,6,2,0]
[0,0,6,1,1]
[0,0,6,0,2]
REV:
[0,1,5,0,2]
[0,2,4,0,2]
[1,1,4,0,2]
[2,0,4,0,2]
i think BFS could actually work.
notice that n*O(n+m) = O(n^2+nm) and therefore not exponential.
also you could use: Floyd-Warshall algorithm and Johnson’s algorithm, with a weight of 1 for a "flat" graph, or even connect the vertices in a new way by their actual distance and potentially save some iterations.
hope it helped :)
void transform(int[] in, int[] out, int size)
{
int[] state = in.clone();
report(state);
while (true)
{
int minPressure = 0;
int indexOfMinPressure = 0;
int maxPressure = 0;
int indexOfMaxPressure = 0;
int pressureSum = 0;
for (int index = 0; index < size - 1; ++index)
{
int lhsDiff = state[index] - out[index];
int rhsDiff = state[index + 1] - out[index + 1];
int pressure = lhsDiff - rhsDiff;
if (pressure < minPressure)
{
minPressure = pressure;
indexOfMinPressure = index;
}
if (pressure > maxPressure)
{
maxPressure = pressure;
indexOfMaxPressure = index;
}
pressureSum += pressure;
}
if (minPressure == 0 && maxPressure == 0)
{
break;
}
boolean shiftLeft;
if (Math.abs(minPressure) > Math.abs(maxPressure))
{
shiftLeft = true;
}
else if (Math.abs(minPressure) < Math.abs(maxPressure))
{
shiftLeft = false;
}
else
{
shiftLeft = (pressureSum < 0);
}
if (shiftLeft)
{
++state[indexOfMinPressure];
--state[indexOfMinPressure + 1];
}
else
{
--state[indexOfMaxPressure];
++state[indexOfMaxPressure + 1];
}
report(state);
}
}
A simple greedy algorithm will work and do the job in minimum number of steps. The function returns the total numbers of steps required for the task.
int shift(std::vector<int>& a,std::vector<int>& b){
int n = a.size();
int sum1=0,sum2=0;
for (int i = 0; i < n; ++i){
sum1+=a[i];
sum2+=b[i];
}
if (sum1!=sum2)
{
return -1;
}
int operations=0;
int j=0;
for (int i = 0; i < n;)
{
if (a[i]<b[i])
{
while(j<n and a[j]==0){
j++;
}
if(a[j]<b[i]-a[i]){
operations+=(j-i)*a[j];
a[i]+=a[j];
a[j]=0;
}else{
operations+=(j-i)*(b[i]-a[i]);
a[j]-=(b[i]-a[i]);
a[i]=b[i];
}
}else if (a[i]>b[i])
{
a[i+1]+=(a[i]-b[i]);
operations+=(a[i]-b[i]);
a[i]=b[i];
}else{
i++;
}
}
return operations;
}
Here -1 is a special value meaning that given array cannot be converted to desired one.
Time Complexity: O(n).
I have an array of size n, which contain elements from 1 to n, in random order. So, we'd have as input an unordered array of integers.
Considering I can swap any two elements any number of times, how can I find minimum numbers of such swap to make array sorted?
This can be done in O(n). Assuming elements are in range 1 to n and there're no duplicates.
noofswaps = 0
for i in range(len(A)):
while A[i] != i + 1:
temp = A[i]
A[i] = A[A[i] - 1]
A[temp - 1] = temp
noofswaps += 1
print noofswaps
static int minimumSwaps(int[] arr) {
int swap=0;
boolean newarr[]=new boolean[arr.length];
for(int i=0;i<arr.length;i++){
int j=i,count=0;
while(!newarr[j]){
newarr[j]=true;
j=arr[j]-1;
count++;
}
if(count!=0)
swap+=count-1;
}
return swap;
}
I'll try to answer this question using javascript.
This is most optimal code I have tried so far :
function minimumSwaps(arr) {
var arrLength = arr.length;
// create two new Arrays
// one record value and key separately
// second to keep visited node count (default set false to all)
var newArr = [];
var newArrVisited = [];
for (let i = 0; i < arrLength; i++) {
newArr[i]= [];
newArr[i].value = arr[i];
newArr[i].key = i;
newArrVisited[i] = false;
}
// sort new array by value
newArr.sort(function (a, b) {
return a.value - b.value;
})
var swp = 0;
for (let i = 0; i < arrLength; i++) {
// check if already visited or swapped
if (newArr[i].key == i || newArrVisited[i]) {
continue;
}
var cycle = 0;
var j = i;
while (!newArrVisited[j]) {
// mark as visited
newArrVisited[j] = true;
j = newArr[j].key; //assign next key
cycle++;
}
if (cycle > 0) {
swp += (cycle > 1) ? cycle - 1 : cycle;
}
}
return swp;
}
reference -1
reference -2
Hackerrank Python code for minimum swaps 2 using hashmaps
length = int(input())
arr= list(map(int,input().split()))
hashmap = {}
for i in range(0,len(arr)):
hashmap[i+1] = [arr[i],False]
swap_count = 0
for e_pos, e_val in hashmap.items():
if e_val[1] == False:
e_val[1] = True
if e_pos == e_val[0]:
continue
else:
c = e_val[0]
while hashmap[c][1] == False:
hashmap[c][1] = True
b = hashmap[c][0]
c = b
swap_count+=1
print(swap_count)
There's an interesting take in GeeksForGeeks with
Time Complexity: O(N) where N is the size of the array.
Auxiliary Space: O(1)
The used approach was
For each index in arr[], check if the current element is in it’s right position or not. Since the array contains distinct elements from 1 to N, we can simply compare the element with it’s index in array to check if it is at its right position.
If current element is not at it’s right position then swap the element with the element which has occupied its place (using temp variable)
Else check for next index (i += 1)
This is the code
def minimumSwaps(arr):
min_num_swaps = 0;
i = 0;
while (i < len(arr)):
if (arr[i] != i + 1):
while (arr[i] != i + 1):
temp = 0;
temp = arr[arr[i] - 1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
min_num_swaps += 1;
i += 1;
return min_num_swaps;
that could easily be updated to
Remove semicolons
Remove the need for temp
Substitute len(arr) with a given integer input n with the size of the array
def minimumSwaps(arr):
min_num_swaps = 0
i = 0
while (i < n-1):
if (arr[i] != i + 1):
while (arr[i] != i + 1):
arr[arr[i] - 1], arr[i] = arr[i], arr[arr[i] - 1]
min_num_swaps += 1
i += 1;
return min_num_swaps
They both are gonna pass all the current 15 Test cases in HackerRank
Here is my code for minimumsawap function using java 7
static int minimumSwaps(int[] arr) {
int c=0;
for(int i=0;i<arr.length;i++){
if(arr[i]!=(i+1)){
int t= arr[i];
arr[i]=arr[t-1];
arr[t-1]=t;
c++;
i=0;
}
}
return c;
}
Recently i have been interviewed. I didn't do well cause i got stuck at the following question
suppose a sequence is given : A D C B D A B C D A C D
and search sequence is like: A C D
task was to find the start and end index in given string that contains all the characters of search string preserving the order.
Output: assuming index start from 1:
start index 10
end index 12
explanation :
1.start/end index are not 1/3 respectively because though they contain the string but order was not maintained
2.start/end index are not 1/5 respectively because though they contain the string in the order but the length is not optimum
3.start/end index are not 6/9 respectively because though they contain the string in the order but the length is not optimum
Please go through How to find smallest substring which contains all characters from a given string?.
But the above question is different since the order is not maintained. I'm still struggling to maintain the indexes. Any help would be appreciated . thanks
I tried to write some simple c code to solve the problem:
Update:
I wrote a search function that looks for the required characters in correct order, returning the length of the window and storing the window start point to ìnt * startAt. The function processes a sub-sequence of given hay from specified startpoint int start to it's end
The rest of the algorithm is located in main where all possible subsequences are tested with a small optimisation: we start looking for the next window right after the startpoint of the previous one, so we skip some unnecessary turns. During the process we keep track f the 'till-now best solution
Complexity is O(n*n/2)
Update2:
unnecessary dependencies have been removed, unnecessary subsequent calls to strlen(...) have been replaced by size parameters passed to search(...)
#include <stdio.h>
// search for single occurrence
int search(const char hay[], int haySize, const char needle[], int needleSize, int start, int * startAt)
{
int i, charFound = 0;
// search from start to end
for (i = start; i < haySize; i++)
{
// found a character ?
if (hay[i] == needle[charFound])
{
// is it the first one?
if (charFound == 0)
*startAt = i; // store starting position
charFound++; // and go to next one
}
// are we done?
if (charFound == needleSize)
return i - *startAt + 1; // success
}
return -1; // failure
}
int main(int argc, char **argv)
{
char hay[] = "ADCBDABCDACD";
char needle[] = "ACD";
int resultStartAt, resultLength = -1, i, haySize = sizeof(hay) - 1, needleSize = sizeof(needle) - 1;
// search all possible occurrences
for (i = 0; i < haySize - needleSize; i++)
{
int startAt, length;
length = search(hay, haySize, needle, needleSize, i, &startAt);
// found something?
if (length != -1)
{
// check if it's the first result, or a one better than before
if ((resultLength == -1) || (resultLength > length))
{
resultLength = length;
resultStartAt = startAt;
}
// skip unnecessary steps in the next turn
i = startAt;
}
}
printf("start at: %d, length: %d\n", resultStartAt, resultLength);
return 0;
}
Start from the beginning of the string.
If you encounter an A, then mark the position and push it on a stack. After that, keep checking the characters sequentially until
1. If you encounter an A, update the A's position to current value.
2. If you encounter a C, push it onto the stack.
After you encounter a C, again keep checking the characters sequentially until,
1. If you encounter a D, erase the stack containing A and C and mark the score from A to D for this sub-sequence.
2. If you encounter an A, then start another Stack and mark this position as well.
2a. If now you encounter a C, then erase the earlier stacks and keep the most recent stack.
2b. If you encounter a D, then erase the older stack and mark the score and check if it is less than the current best score.
Keep doing this till you reach the end of the string.
The pseudo code can be something like:
Initialize stack = empty;
Initialize bestLength = mainString.size() + 1; // a large value for the subsequence.
Initialize currentLength = 0;
for ( int i = 0; i < mainString.size(); i++ ) {
if ( stack is empty ) {
if ( mainString[i] == 'A' ) {
start a new stack and push A on it.
mark the startPosition for this stack as i.
}
continue;
}
For each of the stacks ( there can be at most two stacks prevailing,
one of size 1 and other of size 0 ) {
if ( stack size == 1 ) // only A in it {
if ( mainString[i] == 'A' ) {
update the startPosition for this stack as i.
}
if ( mainString[i] == 'C' ) {
push C on to this stack.
}
} else if ( stack size == 2 ) // A & C in it {
if ( mainString[i] == 'C' ) {
if there is a stack with size 1, then delete this stack;// the other one dominates this stack.
}
if ( mainString[i] == 'D' ) {
mark the score from startPosition till i and update bestLength accordingly.
delete this stack.
}
}
}
}
I modified my previous suggestion using a single queue, now I believe this algorithm runs with O(N*m) time:
FindSequence(char[] sequenceList)
{
queue startSeqQueue;
int i = 0, k;
int minSequenceLength = sequenceList.length + 1;
int startIdx = -1, endIdx = -1;
for (i = 0; i < sequenceList.length - 2; i++)
{
if (sequenceList[i] == 'A')
{
startSeqQueue.queue(i);
}
}
while (startSeqQueue!=null)
{
i = startSeqQueue.enqueue();
k = i + 1;
while (sequenceList.length < k && sequenceList[k] != 'C')
if (sequenceList[i] == 'A') i = startSeqQueue.enqueue();
k++;
while (sequenceList.length < k && sequenceList[k] != 'D')
k++;
if (k < sequenceList.length && k > minSequenceLength > k - i + 1)
{
startIdx = i;
endIdx = j;
minSequenceLength = k - i + 1;
}
}
return startIdx & endIdx
}
My previous (O(1) memory) suggestion:
FindSequence(char[] sequenceList)
{
int i = 0, k;
int minSequenceLength = sequenceList.length + 1;
int startIdx = -1, endIdx = -1;
for (i = 0; i < sequenceList.length - 2; i++)
if (sequenceList[i] == 'A')
k = i+1;
while (sequenceList.length < k && sequenceList[k] != 'C')
k++;
while (sequenceList.length < k && sequenceList[k] != 'D')
k++;
if (k < sequenceList.length && k > minSequenceLength > k - i + 1)
{
startIdx = i;
endIdx = j;
minSequenceLength = k - i + 1;
}
return startIdx & endIdx;
}
Here's my version. It keeps track of possible candidates for an optimum solution. For each character in the hay, it checks whether this character is in sequence of each candidate. It then selectes the shortest candidate. Quite straightforward.
class ShortestSequenceFinder
{
public class Solution
{
public int StartIndex;
public int Length;
}
private class Candidate
{
public int StartIndex;
public int SearchIndex;
}
public Solution Execute(string hay, string needle)
{
var candidates = new List<Candidate>();
var result = new Solution() { Length = hay.Length + 1 };
for (int i = 0; i < hay.Length; i++)
{
char c = hay[i];
for (int j = candidates.Count - 1; j >= 0; j--)
{
if (c == needle[candidates[j].SearchIndex])
{
if (candidates[j].SearchIndex == needle.Length - 1)
{
int candidateLength = i - candidates[j].StartIndex;
if (candidateLength < result.Length)
{
result.Length = candidateLength;
result.StartIndex = candidates[j].StartIndex;
}
candidates.RemoveAt(j);
}
else
{
candidates[j].SearchIndex += 1;
}
}
}
if (c == needle[0])
candidates.Add(new Candidate { SearchIndex = 1, StartIndex = i });
}
return result;
}
}
It runs in O(n*m).
Here is my solution in Python. It returns the indexes assuming 0-indexed sequences. Therefore, for the given example it returns (9, 11) instead of (10, 12). Obviously it's easy to mutate this to return (10, 12) if you wish.
def solution(s, ss):
S, E = [], []
for i in xrange(len(s)):
if s[i] == ss[0]:
S.append(i)
if s[i] == ss[-1]:
E.append(i)
candidates = sorted([(start, end) for start in S for end in E
if start <= end and end - start >= len(ss) - 1],
lambda x,y: (x[1] - x[0]) - (y[1] - y[0]))
for cand in candidates:
i, j = cand[0], 0
while i <= cand[-1]:
if s[i] == ss[j]:
j += 1
i += 1
if j == len(ss):
return cand
Usage:
>>> from so import solution
>>> s = 'ADCBDABCDACD'
>>> solution(s, 'ACD')
(9, 11)
>>> solution(s, 'ADC')
(0, 2)
>>> solution(s, 'DCCD')
(1, 8)
>>> solution(s, s)
(0, 11)
>>> s = 'ABC'
>>> solution(s, 'B')
(1, 1)
>>> print solution(s, 'gibberish')
None
I think the time complexity is O(p log(p)) where p is the number of pairs of indexes in the sequence that refer to search_sequence[0] and search_sequence[-1] where the index for search_sequence[0] is less than the index forsearch_sequence[-1] because it sorts these p pairings using an O(n log n) algorithm. But then again, my substring iteration at the end could totally overshadow that sorting step. I'm not really sure.
It probably has a worst-case time complexity which is bounded by O(n*m) where n is the length of the sequence and m is the length of the search sequence, but at the moment I cannot think of an example worst-case.
Here is my O(m*n) algorithm in Java:
class ShortestWindowAlgorithm {
Multimap<Character, Integer> charToNeedleIdx; // Character -> indexes in needle, from rightmost to leftmost | Multimap is a class from Guava
int[] prefixesIdx; // prefixesIdx[i] -- rightmost index in the hay window that contains the shortest found prefix of needle[0..i]
int[] prefixesLengths; // prefixesLengths[i] -- shortest window containing needle[0..i]
public int shortestWindow(String hay, String needle) {
init(needle);
for (int i = 0; i < hay.length(); i++) {
for (int needleIdx : charToNeedleIdx.get(hay.charAt(i))) {
if (firstTimeAchievedPrefix(needleIdx) || foundShorterPrefix(needleIdx, i)) {
prefixesIdx[needleIdx] = i;
prefixesLengths[needleIdx] = getPrefixNewLength(needleIdx, i);
forgetOldPrefixes(needleIdx);
}
}
}
return prefixesLengths[prefixesLengths.length - 1];
}
private void init(String needle) {
charToNeedleIdx = ArrayListMultimap.create();
prefixesIdx = new int[needle.length()];
prefixesLengths = new int[needle.length()];
for (int i = needle.length() - 1; i >= 0; i--) {
charToNeedleIdx.put(needle.charAt(i), i);
prefixesIdx[i] = -1;
prefixesLengths[i] = -1;
}
}
private boolean firstTimeAchievedPrefix(int needleIdx) {
int shortestPrefixSoFar = prefixesLengths[needleIdx];
return shortestPrefixSoFar == -1 && (needleIdx == 0 || prefixesLengths[needleIdx - 1] != -1);
}
private boolean foundShorterPrefix(int needleIdx, int hayIdx) {
int shortestPrefixSoFar = prefixesLengths[needleIdx];
int newLength = getPrefixNewLength(needleIdx, hayIdx);
return newLength <= shortestPrefixSoFar;
}
private int getPrefixNewLength(int needleIdx, int hayIdx) {
return needleIdx == 0 ? 1 : (prefixesLengths[needleIdx - 1] + (hayIdx - prefixesIdx[needleIdx - 1]));
}
private void forgetOldPrefixes(int needleIdx) {
if (needleIdx > 0) {
prefixesLengths[needleIdx - 1] = -1;
prefixesIdx[needleIdx - 1] = -1;
}
}
}
It works on every input and also can handle repeated characters etc.
Here are some examples:
public class StackOverflow {
public static void main(String[] args) {
ShortestWindowAlgorithm algorithm = new ShortestWindowAlgorithm();
System.out.println(algorithm.shortestWindow("AXCXXCAXCXAXCXCXAXAXCXCXDXDXDXAXCXDXAXAXCD", "AACD")); // 6
System.out.println(algorithm.shortestWindow("ADCBDABCDACD", "ACD")); // 3
System.out.println(algorithm.shortestWindow("ADCBDABCD", "ACD")); // 4
}
I haven't read every answer here, but I don't think anyone has noticed that this is just a restricted version of local pairwise sequence alignment, in which we are only allowed to insert characters (and not delete or substitute them). As such it will be solved by a simplification of the Smith-Waterman algorithm that considers only 2 cases per vertex (arriving at the vertex either by matching a character exactly, or by inserting a character) rather than 3 cases. This algorithm is O(n^2).
Here's my solution. It follows one of the pattern matching solutions. Please comment/correct me if I'm wrong.
Given the input string as in the question
A D C B D A B C D A C D. Let's first compute the indices where A occurs. Assuming a zero based index this should be [0,5,9].
Now the pseudo code is as follows.
Store the indices of A in a list say *orders*.// orders=[0,5,9]
globalminStart, globalminEnd=0,localMinStart=0,localMinEnd=0;
for (index: orders)
{
int i =index;
Stack chars=new Stack();// to store the characters
i=localminStart;
while(i< length of input string)
{
if(str.charAt(i)=='C') // we've already seen A, so we look for C
st.push(str.charAt(i));
i++;
continue;
else if(str.charAt(i)=='D' and st.peek()=='C')
localminEnd=i; // we have a match! so assign value of i to len
i+=1;
break;
else if(str.charAt(i)=='A' )// seen the next A
break;
}
if (globalMinEnd-globalMinStart<localMinEnd-localMinStart)
{
globalMinEnd=localMinEnd;
globalMinStart=localMinStart;
}
}
return [globalMinstart,globalMinEnd]
}
P.S: this is pseudocode and a rough idea. Id be happy to correct it and understand if there's something wrong.
AFAIC Time complexity -O(n). Space complexity O(n)
Given a set {1,2,3,4,5...n} of n elements, we need to find all subsets of length k .
For example, if n = 4 and k = 2, the output would be {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}.
I am not even able to figure out how to start. We don't have to use the inbuilt library functions like next_permutation etc.
Need the algorithm and implementation in either C/C++ or Java.
Recursion is your friend for this task.
For each element - "guess" if it is in the current subset, and recursively invoke with the guess and a smaller superset you can select from. Doing so for both the "yes" and "no" guesses - will result in all possible subsets.
Restraining yourself to a certain length can be easily done in a stop clause.
Java code:
private static void getSubsets(List<Integer> superSet, int k, int idx, Set<Integer> current,List<Set<Integer>> solution) {
//successful stop clause
if (current.size() == k) {
solution.add(new HashSet<>(current));
return;
}
//unseccessful stop clause
if (idx == superSet.size()) return;
Integer x = superSet.get(idx);
current.add(x);
//"guess" x is in the subset
getSubsets(superSet, k, idx+1, current, solution);
current.remove(x);
//"guess" x is not in the subset
getSubsets(superSet, k, idx+1, current, solution);
}
public static List<Set<Integer>> getSubsets(List<Integer> superSet, int k) {
List<Set<Integer>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new HashSet<Integer>(), res);
return res;
}
Invoking with:
List<Integer> superSet = new ArrayList<>();
superSet.add(1);
superSet.add(2);
superSet.add(3);
superSet.add(4);
System.out.println(getSubsets(superSet,2));
Will yield:
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
Use a bit vector representation of the set, and use an algorithm similar to what std::next_permutation does on 0000.1111 (n-k zeroes, k ones). Each permutation corresponds to a subset of size k.
This is python. Sorry for the spanish ;)
from pprint import pprint
conjunto = [1,2,3,4, 5,6,7,8,9,10]
k = 3
lista = []
iteraciones = [0]
def subconjuntos(l, k):
if k == len(l):
if not l in lista:
lista.append(l)
return
for i in l:
aux = l[:]
aux.remove(i)
result = subconjuntos(aux, k)
iteraciones[0] += 1
if not result in lista and result:
lista.append( result)
subconjuntos(conjunto, k)
print (lista)
print ('cant iteraciones: ' + str(iteraciones[0]))
Check out my solution
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class Subset_K {
public static void main(String[]args)
{
Set<String> x;
int n=4;
int k=2;
int arr[]={1,2,3,4};
StringBuilder sb=new StringBuilder();
for(int i=1;i<=(n-k);i++)
sb.append("0");
for(int i=1;i<=k;i++)
sb.append("1");
String bin=sb.toString();
x=generatePerm(bin);
Set<ArrayList <Integer>> outer=new HashSet<ArrayList <Integer>>();
for(String s:x){
int dec=Integer.parseInt(s,2);
ArrayList<Integer> inner=new ArrayList<Integer>();
for(int j=0;j<n;j++){
if((dec&(1<<j))>0)
inner.add(arr[j]);
}
outer.add(inner);
}
for(ArrayList<?> z:outer){
System.out.println(z);
}
}
public static Set<String> generatePerm(String input)
{
Set<String> set = new HashSet<String>();
if (input == "")
return set;
Character a = input.charAt(0);
if (input.length() > 1)
{
input = input.substring(1);
Set<String> permSet = generatePerm(input);
for (String x : permSet)
{
for (int i = 0; i <= x.length(); i++)
{
set.add(x.substring(0, i) + a + x.substring(i));
}
}
}
else
{
set.add(a + "");
}
return set;
}
}
I am working on a 4 element set for test purpose and using k=2. What I try to do is initially generate a binary string where k bits are set and n-k bits are not set. Now using this string I find all the possible permutations of this string. And then using these permutations I output the respective element in the set. Would be great if someone could tell me about the complexity of this problem.
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int> v;
vector<vector<int> > result;
void subset(int arr[],int k,int n,int idx){
if(idx==n)
return;
if(k==1){
for(int i=idx;i<n;i++)
{
v.push_back(arr[i]);
result.push_back(v);
v.pop_back();
}
}
for(int j=idx;j<n;j++) {
v.push_back(arr[j]);
subset(arr,k-1,n,j+1);
v.pop_back();
}
}
int main(){
int arr[] = {1,2,3,4,5,6,7};
int k = 4;
int n =sizeof(arr)/sizeof(arr[0]);
subset(arr,k,n,0);
for(int i = 0;i<result.size();i++)
{
for(int j = 0;j<result[i].size();j++)
{
cout << result[i][j] << " ";
}
cout << endl;
}
}
Another intresting solution.
#include<bits/stdc++.h>
using namespace std;
long factorial(int n) { return (n==1|| n==0|| n < 0) ? 1 : n *factorial(n-1) ;}
void printS(int set[],int n,int k)
{
long noofsubset = factorial(n) / (factorial(n-k)*factorial(k));
bitset<32> z ((1 << (k)) - 1);
string s = z.to_string();
int i = 0;
while(i<noofsubset)
{
for (int j = 0; j < n;j++)
{
if(s[(32-n)+j] == '1')
cout << set[j]<<" ";
}
cout << endl;
next_permutation(s.begin(),s.end());
i++;
}
}
void printSubsetsOfArray(int input[], int size) {
int k = 3;
printS(input,size,k) ;
}
Slight improvement for #amit top voted answer:
His code keep checking combinations even when there won't be any chance for them to reach the wanted length. We can stop creating combinations much earlier:
e.g. for [1,2,3,4,5,6,7,8,9,10] , length = 8 , the code will still try all combinations of length 7,6,5,4,3,2,1 although they will obviously just be thrown away, halting only when idx reaches the end of the list.
We can improve the running time by stopping earlier, when we already know the set we build + the optional remaining digits will still be too short.
change :
//unsuccessful stop clause
if (idx == superSet.size()) return;
into:
// unsuccessful stop clause
Integer maxFutureElements = superSet.size() - idx;
if (current.size() + maxFutureElements < length) return;
Please check my solution:-
private static void printPermutations(List<Integer> list, int subSetSize) {
List<Integer> prefixList = new ArrayList<Integer>();
printPermutations(prefixList, list, subSetSize);
}
private static void printPermutations(List<Integer> prefixList, List<Integer> list, int subSetSize) {
if (prefixList.size() == subSetSize) {
System.out.println(prefixList);
} else {
for (int i = 0; i < list.size(); i++) {
Integer removed = list.remove(i);
prefixList.add(removed);
printPermutations(prefixList, list, subSetSize);
prefixList.remove(removed);
list.add(i, removed);
}
}
}
This is similar to String permutations:-
private static void printPermutations(String str) {
printAllPermutations("", str);
}
private static void printAllPermutations(String prefix, String restOfTheString) {
int len = restOfTheString.length();
System.out.println(prefix);
for (int i = 0; i < len; i++) {
printAllPermutations(prefix + restOfTheString.charAt(i), restOfTheString.substring(0, i) + restOfTheString.substring(i + 1, len));
}
}
This is an implemation in F#:
// allSubsets: int -> int -> Set<Set<int>>
let rec allSubsets n k =
match n, k with
| _, 0 -> Set.empty.Add(Set.empty)
| 0, _ -> Set.empty
| n, k -> Set.union (Set.map (fun s -> Set.add n s) (allSubsets (n-1) (k-1)))
(allSubsets (n-1) k)
You can try it in the F# REPL:
> allSubsets 3 2;;
val it : Set<Set<int>> = set [set [1; 2]; set [1; 3]; set [2; 3]]
> allSubsets 4 2;;
val it : Set<Set<int>> = set [set [1; 2]; set [1; 3]; set [1; 4]; set [2; 3]; set [2; 4]; set [3; 4]]
This Java class implements the same algorithm:
import java.util.HashSet;
import java.util.Set;
public class AllSubsets {
public static Set<Set<Integer>> allSubsets(int setSize, int subsetSize) {
if (subsetSize == 0) {
HashSet<Set<Integer>> result = new HashSet<>();
result.add(new HashSet<>());
return result;
}
if (setSize == 0) {
return new HashSet<>();
}
Set<Set<Integer>> sets1 = allSubsets((setSize - 1), (subsetSize - 1));
for (Set<Integer> set : sets1) {
set.add(setSize);
}
Set<Set<Integer>> sets2 = allSubsets((setSize - 1), subsetSize);
sets1.addAll(sets2);
return sets1;
}
}
If you do not like F# or Java then visit this website. It lists solutions to your particular problem in various programming languages:
http://rosettacode.org/wiki/Combinations
JavaScript implementation:
var subsetArray = (function() {
return {
getResult: getResult
}
function getResult(array, n) {
function isBigEnough(value) {
return value.length === n;
}
var ps = [
[]
];
for (var i = 0; i < array.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(array[i]));
}
}
return ps.filter(isBigEnough);
}
})();
var arr = [1, 2, 3, 4,5,6,7,8,9];
console.log(subsetArray.getResult(arr,2));
Here is an iterative version in python. Essence of it is increment_counters() function which returns all possible combinations. We know it needs to be called C(n,r) times.
def nchooser(n,r):
"""Calculate the n choose r manual way"""
import math
f = math.factorial
return f(n) / f(n-r) / f(r)
def increment_counters(rc,r,n):
"""This is the essense of the algorithm. It generates all possible indexes.
Ex: for n = 4, r = 2, rc will have values (0,1),(0,2),(0,3),(1,2),(1,3),(2,3).
You may have better understanding if you print all possible 35 values for
n = 7, r = 3."""
rc[r-1] += 1 # first increment the least significant counter
if rc[r-1] < n: # if it does not overflow, return
return
# overflow at the last counter may cause some of previous counters to overflow
# find where it stops (ex: in n=7,r=3 case, 1,2,3 will follow 0,5,6)
for i in range(r-2,-1,-1): # from r-2 to 0 inclusive
if rc[i] < i+n-r:
break
# we found that rc[i] will not overflow. So, increment it and reset the
# counters right to it.
rc[i] += 1
for j in range(i+1,r):
rc[j] = rc[j-1] + 1
def combinations(lst, r):
"""Return all different sub-lists of size r"""
n = len(lst)
rc = [ i for i in range(r) ] # initialize counters
res = []
for i in range(nchooser(n,r)): # increment the counters max possible times
res.append(tuple(map(lambda k: lst[k],rc)))
increment_counters(rc,r,n)
return res
Here is a Java version of what I think Simple is talking about, using a binary representation of all sets in the power set. It's similar to how Abhiroop Sarkar did it, but I think a boolean array makes more sense than a string when you are just representing binary values.
private ArrayList<ArrayList<Object>> getSubsets(int m, Object[] objects){
// m = size of subset, objects = superset of objects
ArrayList<ArrayList<Object>> subsets = new ArrayList<>();
ArrayList<Integer> pot = new ArrayList<>();
int n = objects.length;
int p = 1;
if(m==0)
return subsets;
for(int i=0; i<=n; i++){
pot.add(p);
p*=2;
}
for(int i=1; i<p; i++){
boolean[] binArray = new boolean[n];
Arrays.fill(binArray, false);
int y = i;
int sum = 0;
for(int j = n-1; j>=0; j--){
int currentPot = pot.get(j);
if(y >= currentPot){
binArray[j] = true;
y -= currentPot;
sum++;
}
if(y<=0)
break;
}
if(sum==m){
ArrayList<Object> subsubset = new ArrayList<>();
for(int j=0; j < n; j++){
if(binArray[j]){
subsubset.add(objects[j]);
}
}
subsets.add(subsubset);
}
}
return subsets;
}
If you are looking for Iterator pattern answer then here you go.
public static <T> Iterable<List<T>> getList(final Iterable<? extends T> list) {
List<List<T>> listOfList = new ArrayList<>();
for (T t: list)
listOfList.add(Collections.singletonList(t));
return listOfList;
}
public static <T> Iterable<List<T>> getIterable(final Iterable<? extends T> list, final int size) {
final List<T> vals = new ArrayList<>();
int numElements = 0;
for (T t : list) {
vals.add(t);
numElements++;
}
if (size == 1) {
return getList(vals);
}
if (size == numElements) {
return Collections.singletonList(vals);
}
return new Iterable<List<T>>() {
#Override
public Iterator<List<T>> iterator() {
return new Iterator<List<T>>() {
int currPos = 0;
Iterator<List<T>> nextIterator = getIterable(
vals.subList(this.currPos + 1, vals.size()), size - 1).iterator();
#Override
public boolean hasNext() {
if ((this.currPos < vals.size()-2) && (this.currPos+size < vals.size()))
return true;
return false;
}
#Override
public List<T> next() {
if (!nextIterator.hasNext()) {
this.currPos++;
nextIterator = getIterable(vals.subList(this.currPos+1, vals.size()), size-1).iterator();
}
final List<T> ret = new ArrayList<>(nextIterator.next());
ret.add(0, vals.get(this.currPos));
return ret;
}
};
}
};
}
Here's a short python algorithm. I haven't used any predefined functions as such so I believe it could be easily translated to Java/C
def subs(l,n):
if(len(l)<k):
return []
elif(k==0):
return [[]]
else:
lis=[[l[0]]+b for b in (subs(l[1:],k-1))]
return (lis+subs(l[1:],k))
Here l is the list [1,2,...,m]
Here is a simple algorithm to enumerate all k-subsets of [n]={0,...,n-1} in lexicographic order. That is, the first of these subsets is S0=(0,1,2...,k-1), and the last is Slast=(n-k, n-k+1,...,n-1). For any k-subset S and for any 0 < j < k, we have S[j-1] < S[j] <= n+j-k.
For example, if n=10 and k=4, S0=(0,1,2,3) and Slast=(6,7,8,9). Notice, for example, that no combination can have S[1]>7 (in which case we'd have S[j]>n+j-k), since then there would be not enough values left to fill thr remaining positions j=2..3.
The idea of the algorithm is to start with the first combination S0, and then call next() repeatedly to generate the next k-subset each time. The function next() traverses the current k-subset backwards, starting from the last position j=k-1 down to 0, until it finds an entry S[j] that has not yet reached its maximum allowed value n+j-k and can thus be increased. Then it increases this position by one and fills the remaining positions, j+1..k-1 with consecutive values from S[j]+1. The algorithm stops as soon as no position can be further increased.
For example, suppose we have S=(3,7,8,9). Starting from j=3, we see that S[3],S[2],S[1] have reached their maximum values. Thus, the rightmost position that can still be increased is S[0]. This value is updated to S[0]+1=4, and the following positions are updated to 5,6,7. Hence the next k-subset will be S=(4,5,6,7).
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
bool next(int *S, int k, int n) {
int j = k-1;
while (j >= 0 && S[j] == n + j - k)
j--;
if (j < 0) return false;
S[j] += 1;
for (int i = j+1; i < k ; i++)
S[i] = S[i-1] + 1;
return true;
}
int main(int argc, char *argv[])
{
int n = 10;
int k = 4;
int *S = (int *)calloc(k, sizeof(int));
for (int j = 0; j < k; S[++j] = j); //first k-subset
int no = 0;
do {
printf("subset #%d: ",no++);
for (int j=0; j < k; j++) {
printf("%d ", S[j]);
}
printf("\n");
} while(next(S, k, n));
return 0;
}