Related
Every positive integer divide some number whose representation (base 10) contains only zeroes and ones.
One can prove that:
Consider the numbers 1, 11, 111, 1111, etc. up to 111... 1, where the
last number has n+1 digits. Call these numbers m1, m2, ... , mn+1. Each has a
remainder when divided by n, and two of these remainders must be the same.
Because there are n+1 of them but only n values a remainder can take.
This is an application of the famous and useful “pigeonhole principle”;
Suppose the two numbers with the same remainder are mi and mj
, with i < j. Now subtract the smaller from the larger. The resulting number, mi−mj, consisting of j - i ones followed by i zeroes, must be a multiple of n.
But how to find the smallest answer? and effciently?
The question equals to using 10i mod n (for each i, it can be used at most once) to get a sum m of n. It's like a knapsack problem or subset sum problem. In this way, dynamic programming will do the task.
In dynamic programming the complexity is O(k*n). k is the number of digits in answer. For n<105, this code works perfectly.
Code:
#include <stdio.h>
#define NUM 2000
int main(int argc, char* argv[])
{
signed long pow[NUM],val[NUM],x,num,ten;
int i,j,count;
for(num=2; num<NUM; num++)
{
for(i=0; i<NUM; pow[i++]=0);
count=0;
for(ten=1,x=1; x<NUM; x++)
{
val[x]=ten;
for(j=0; j<NUM; j++)if(pow[j]&&!pow[(j+ten)%num]&&pow[j]!=x)pow[(j+ten)%num]=x;
if(!pow[ten])pow[ten]=x;
ten=(10*ten)%num;
if(pow[0])break;
}
x=num;
printf("%ld\tdivides\t",x=num);
if(pow[0])
{
while(x)
{
while(--count>pow[x%num]-1)printf("0");
count=pow[x%num]-1;
printf("1");
x=(num+x-val[pow[x%num]])%num;
}
while(count-->0)printf("0");
}
printf("\n");
}
}
PS:
This sequence in OEIS.
Nice question. I use BFS to solve this question with meet-in-the-middle and some other prunings. Now my code can solve n<109 in a reasonable time.
#include <cstdio>
#include <cstring>
class BIT {
private: int x[40000000];
public:
void clear() {memset(x, 0, sizeof(x));}
void setz(int p, int z) {x[p>>5]=z?(x[p>>5]|(1<<(p&31))):(x[p>>5]&~(1<<(p&31)));}
int bit(int p) {return x[p>>5]>>(p&31)&1;}
} bp, bq;
class UNIT {
private: int x[3];
public: int len, sum;
void setz(int z) {x[len>>5]=z?(x[len>>5]|(1<<(len&31))):(x[len>>5]&~(1<<(len&31)));}
int bit(int p) {return x[p>>5]>>(p&31)&1;}
} u;
class MYQUEUE {
private: UNIT x[5000000]; int h, t;
public:
void clear() {h = t = 0;}
bool empty() {return h == t;}
UNIT front() {return x[h];}
void pop() {h = (h + 1) % 5000000;}
void push(UNIT tp) {x[t] = tp; t = (t + 1) % 5000000;}
} p, q;
int n, md[100];
void bfs()
{
for (int i = 0, tp = 1; i < 200; i++) tp = 10LL * (md[i] = tp) % n;
u.len = -1; u.sum = 0; q.clear(); q.push(u); bq.clear();
while (1)
{
u = q.front(); if (u.len >= 40) break; q.pop();
u.len++; u.setz(0); q.push(u);
u.setz(1); u.sum = (u.sum + md[u.len]) % n;
if (!bq.bit(u.sum)) {bq.setz(u.sum, 1); q.push(u);}
if (!u.sum) {
for (int k = u.len; k >= 0; k--) printf("%d", u.bit(k));
puts(""); return;
}
}
u.len = 40; u.sum = 0; p.clear(); p.push(u); bp.clear();
while (1)
{
u = p.front(); p.pop();
u.len++; u.setz(0); p.push(u);
u.setz(1); u.sum = (u.sum + md[u.len]) % n;
if (!bp.bit(u.sum)) {bp.setz(u.sum, 1); p.push(u);}
int bf = (n - u.sum) % n;
if (bq.bit(bf)) {
for (int k = u.len; k > 40; k--) printf("%d", u.bit(k));
while (!q.empty())
{
u = q.front(); if (u.sum == bf) break; q.pop();
}
for (int k = 40; k >= 0; k--) printf("%d", u.bit(k));
puts(""); return;
}
}
}
int main(void)
{
// 0 < n < 10^9
while (~scanf("%d", &n)) bfs();
return 0;
}
There's an O(n)-time (arithmetic operations mod n, really) solution, which is more efficient than the answer currently accepted. The idea is to construct a graph on vertices 0..n-1 where vertex i has connections to (i*10)%n and (i*10+1)%n, then use breadth-first search to find the lexicographically least path from 1 to 0.
def smallest(n):
parents = {}
queue = [(1 % n, 1, None)]
i = 0
while i < len(queue):
residue, digit, parent = queue[i]
i += 1
if residue in parents:
continue
if residue == 0:
answer = []
while True:
answer.append(str(digit))
if parent is None:
answer.reverse()
return ''.join(answer)
digit, parent = parents[parent]
parents[residue] = (digit, parent)
for digit in (0, 1):
queue.append(((residue * 10 + digit) % n, digit, residue))
return None
Here is a readable solution using BFS in java. The approach is similar to David's with some improvements.
You build a decision tree of whether to append a 0 or 1 and perform BFS to find the lowest such valid multiple of the input number.
This solution also leverages modulo (of the input number) to compute really large results. Full description available in the comments in the code.
You can also access the same code snippet in ideone.
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
public class Main {
// Return the smallest multiple of the number (as a string) consisting only of digits 0 and 1
//
// All possible digits that can be constructed using the digits 0/1 can be represented
// as a tree, where at each level, appending a 0 is one branch and appending a 1 is another
//
// If we perform BFS on this tree, the first number we see which is an exact multiple of the input
// number will be the result (since it will be the smallest). Make sure to consider left
// branch (i.e. 0) before considering the right branch (i.e. 1)
//
// The 2 paths we take at each level when the current number is num:
// (num * 10)
// (num * 10) + 1
//
// Since the result can grow huge quite easily, it might not be possible to store the result in a
// 32 or even a 64 bit int/long variable.
//
// One alternative is to use BigNumber, but a simpler alternative exists if we leverage modulo.
//
// The operations we perform above (i.e. multiplications and additions) will retain the useful part
// of the result when using modulo. We use the given number itself as the modulo, and when we see a
// result of 0, it means we have found a number which is an exact multiple of the input number.
//
// To reconstruct the number, we need to store the parent nodes of each node, when adding the node
// in the queue (similar to using BFS for computing shortest path)
//
// We will also need to know if we appended a 0 or a 1 at each step, and so we add this information
// as part of the node data structure as well.
//
// Re-visiting nodes is unecessary since we have seen this modulo result (i.e. value % num) already.
// Any additional digits we add from now will only make the number longer and we already are tracking
// the path for this same modulo result we've seen earlier.
//
public static String multiple(int num) {
if (num < 0) {
throw new IllegalArgumentException("Invalid args");
}
String result = "0";
if (num > 0) {
// An array to mark all the visited nodes
boolean[] isVisited = new boolean[num];
Arrays.fill(isVisited, false);
// The queue used by BFS
Queue<Node> queue = new ArrayDeque<>();
// Add the first number 1 and mark it visited
queue.add(new Node(true, 1 % num, null));
isVisited[1 % num] = true;
// The final destination node which represents the answer
Node destNode = null;
while (!queue.isEmpty()) {
// Get the next node from the queue
Node currNode = queue.remove();
if (currNode.val == 0) {
// We have reached a valid multiple of num
destNode = currNode;
break;
} else {
// Visit the next 2 neighbors
// Append 0 - (currNode.val * 10)
// Append 1 - (currNode.val * 10) + 1
// Append a '0'
int val1 = (currNode.val * 10) % num;
if (!isVisited[val1]) {
queue.add(new Node(false, val1, currNode));
isVisited[val1] = true;
}
// Append a '1'
int val2 = (val1 + 1) % num;
if (!isVisited[val2]) {
queue.add(new Node(true, val2, currNode));
isVisited[val2] = true;
}
}
}
// Trace the path from destination to source
if (destNode == null) {
throw new IllegalStateException("Result should not be null");
} else {
StringBuilder reverseResultBuilder = new StringBuilder();
Node currNode = destNode;
while (currNode != null) {
reverseResultBuilder.append(currNode.isDigitOne ? '1' : '0');
currNode = currNode.parent;
}
result = reverseResultBuilder.reverse().toString();
}
}
return result;
}
// Node represents every digit being appended in the decision tree
private static class Node {
// True if '1', false otherwise (i.e. '0')
public final boolean isDigitOne;
// The number represented in the tree modulo the input number
public final int val;
// The parent node in the tree
public final Node parent;
public Node(boolean isDigitOne, int val, Node parent) {
this.isDigitOne = isDigitOne;
this.val = val;
this.parent = parent;
}
}
public static void main(String[] args) {
int num = new Scanner(System.in).nextInt();
System.out.println("Input number: " + num);
System.out.println("Smallest multiple using only 0s and 1s as digits: " + Main.multiple(num));
}
}
I think this is a fair and interesting question.
Please note that though what you describe is a proof there always exist such number, the found number will not always be minimal.
Only solution I can think of is to compute the remainders of the powers of 10 modulus the given n and than try to construct a sum giving remainder 0 modulo n using at most one of each of these powers. You will never need more than n different powers(which you prove i your question).
This is a fast way to get the first 792 answers. Def the most simple code:
__author__ = 'robert'
from itertools import product
def get_nums(max_length):
assert max_length < 21 #Otherwise there will be over 2 million possibilities
for length in range(1, max_length + 1):
for prod in product("10", repeat=length):
if prod[0] == '1':
yield int("".join(prod))
print list(get_nums(4))
[1, 11, 10, 111, 110, 101, 100, 1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000]
nums = sorted(get_nums(20))
print len(nums)
solution = {}
operations = 0
for factor in range(1, 1000):
for num in nums:
operations += 1
if num % factor == 0:
solution[factor] = num
break
print factor, operations
if factor not in solution:
print "no solution for factor %s" % factor
break
print solution[787]
max_v = max(solution.values())
for factor, val in solution.items():
if val == max_v:
print factor, max_v
[1, 11, 10, 111, 110, 101, 100, 1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000]
1048575
1 1
2 3
3 10
4 14
5 16
6 30
7 39
8 47
9 558
10 560
11 563
12 591
13 600
14 618
15 632
16 648
17 677
18 1699
19 1724
20 1728
..
..
187 319781
188 319857
..
..
791 4899691
792 5948266
no solution for factor 792
10110001111
396 11111111111111111100
Here is a C# solution using linked list
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
public static void print(LinkedList<int> lst)
{
foreach(int i in lst)
{
Console.Write(i);
}
}
static void Main(string[] args)
{
int number = Convert.ToInt32(Console.ReadLine());
int product;
LinkedList<int> list = new LinkedList<int>();
bool Istrue = true;
int range = 1;
while (range <= 10) {
Istrue = true;
product = number * range;
while (product > 0)
{
list.AddFirst(product % 10);
product /= 10;
}
foreach (int i in list)
{
if (i > 1) Istrue = false;
}
if (Istrue) { print(list); break; }
else
{
list.Clear();
}
range++;
}
Console.WriteLine("Done");
string s = Console.ReadLine();
}
}
}
My algorithm will be :-
1)Construct the sorted tree of of n possible numbers(say n initially is 10). So in this example it will contain 1,10,11,100,101,110,111....
2)Then loop over the list and perform on each no x%GivenNo, if its o its smallest possible no
3)Otherwise repeat step 3 with another 10 numbers
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Class1
{
public static void Main()
{
List<string> possibleCombination = new List<string>();
for (int i = 2; i < 10000; i++)
{
possibleCombination.Add(Convert.ToString(i, 2));
}
var input = Console.ReadLine();
long output = 0;
foreach (var item in possibleCombination)
{
if (Convert.ToInt64(item) % Convert.ToInt64(i) == 0)
{
output = Convert.ToInt64(item);
break;
}
}
Console.WriteLine(output);
Console.ReadLine();
}
}
}
Here is complete c# code in O(n) using graph and bfs approach.
using System;
using System.Collections.Generic;
using System.Collections;
using System.Security.Cryptography;
using System.Linq;
using System.Runtime.InteropServices;
class Solution {
public class Edge : IComparable
{
public int From
{
get;
set;
}
public int To
{
get;
set;
}
public int Weight
{
get;
set;
}
public bool IsDirected
{
get;
set;
}
public Edge(int from, int to, bool isDirected = false, int weight = 0)
{
this.From = from;
this.To = to;
this.Weight = weight;
this.IsDirected = isDirected;
}
public int CompareTo(object obj)
{
if (obj is Edge)
{
var comparingTo = obj as Edge;
return this.Weight.CompareTo(comparingTo.Weight);
}
return 0; //TODO:what should we return?
}
}
public class AdjNode
{
public int EdgeWeight
{
get;
set;
}
public int Id
{
get;
set;
}
public AdjNode(int id)
{
this.Id = id;
this.EdgeWeight = 0;
}
public AdjNode(int id, int weight)
{
this.Id = id;
this.EdgeWeight = weight;
}
}
public class GraphAdj
{
public int V
{
get;
set;
}
public List<AdjNode>[] adj
{
get;
set;
}
public List<Edge> Edges
{
get;
set;
}
public GraphAdj(int v)
{
this.V = v;
this.adj = new List<AdjNode>[this.V];
for (int i = 0; i < this.V; i++)
{
this.adj[i] = new List<AdjNode>(); //allocate actual memory
}
this.Edges = new List<Edge>();
}
public void AddDirectedEdge(int from, int to)
{
adj[from].Add(new AdjNode(to));
this.Edges.Add(new Edge(from,to,true));
}
public void AddDirectedEdge(int from, int to, int weight)
{
adj[from].Add(new AdjNode(to,weight));
this.Edges.Add(new Edge(from, to, true, weight));
}
}
public string multiple(int A) {
int n = A;
GraphAdj directedGraphForNumber = new GraphAdj(n);
Queue<int> queueForNumbers = new Queue<int>();
string result = String.Empty;
bool[] visitedForNumbers = new bool[directedGraphForNumber.V];
int[] suffixes = new int[2] { 0, 1 };
//we will start from 1st node out of n node
queueForNumbers.Enqueue(1);
visitedForNumbers[1] = true;
while (true)
{
int from = queueForNumbers.Dequeue();
if (from == 0)
break;
for (int i = 0; i < suffixes.Length; i++)
{
int toNode = from * 10 + suffixes[i];
int reminder = toNode % n;
if (visitedForNumbers[reminder] == false)
{
visitedForNumbers[reminder] = true;
queueForNumbers.Enqueue(reminder);
directedGraphForNumber.AddDirectedEdge(from, reminder,suffixes[i]);
}
}
}
//Do BFS traversal with edges until zero th node encounters
bool[] visitedForBfs = new bool[directedGraphForNumber.V];
Queue<int> queueForBfs = new Queue<int>();
int[] parent = new int[directedGraphForNumber.V];
int source = 1;
visitedForBfs[source] = true;
queueForBfs.Enqueue(source);
parent[source] = -1;
while (queueForBfs.Count > 0)
{
int currentVertex = queueForBfs.Dequeue();
foreach (var adjacentVertex in directedGraphForNumber.adj[currentVertex])
{
if (visitedForBfs[adjacentVertex.Id] == false)
{
queueForBfs.Enqueue(adjacentVertex.Id);
parent[adjacentVertex.Id] = currentVertex;
visitedForBfs[adjacentVertex.Id] = true;
}
if (adjacentVertex.Id == 0) // we reach zero th node
{
queueForBfs.Clear(); //break out of bfs
}
}
}
//now time to find path all the way to start from zero using parent
List<int> pathListUsingParent = new List<int>();
int current = 0;
pathListUsingParent.Add(0); // add zero
while (current!=1)
{
pathListUsingParent.Add(parent[current]);
current = parent[current];
}
//reverse path to make number using edges
pathListUsingParent.Reverse();
result += "1"; //start node
//now read edges
for (int i = 0; i < pathListUsingParent.Count-1; i++)
{
int from = pathListUsingParent[i];
int to = pathListUsingParent[i + 1];
result += directedGraphForNumber.adj[from].FirstOrDefault(adj => adj.Id == to).EdgeWeight;
}
return result;
}
}
Here's a brute force version in Raku:
say (1..Inf).map( *.base(2) ).first( * %% $n );
The code generates a lazy (potentially infinite) sequence of candidate numbers and then searches for the first element that's divisible by n.
Being brute force it's not exceptionally fast, but the code is striking in its simplicity and expressiveness, as it is typical for Raku.
This is not a homework, just a self-practice on recursion. :)
The problem: (http://practiceit.cs.washington.edu/problem.jsp?category=Building+Java+Programs%2C+3rd+edition%2FBJP3+Chapter+12&problem=bjp3-12-e21-maxSum)
Given a integer List L and a limit n, find the maxSum(L,n) that does not exceed the limit n.
Example, L=[7, 30, 8, 22, 6, 1, 14], and Limit n=19, then the maxSum(L,n)=16. Because the max combination is 7+8+1=16.
I've figured out the classical backtracking algorithm to solve this problem:
public static int maxSum(List<Integer> L, int limit){
boolean[] used = new boolean[L.size()];
int[] max = {0};
rec(L, limit, 0, used, max);
return max[0];
}
public static boolean rec(List<Integer> L, int limit, int cur, boolean[] used, int[] max){
if(cur > limit){
return false;
}
for(int i=0; i<L.size(); i++){
if(!used[i]){
used[i] = true;
if(rec(L, limit, cur+L.get(i), used, max)){
max[0] = Math.max(max[0], cur+L.get(i));
}
used[i] = false;
}
}
return true;
}
However, since this problem does not allow any loop in the program. So I'm wondering if there is way to remove the for loop in my rec() function.
Thank you very much!
Of course it is possible, every loop can be replaced with recursion.
for(int i = 0; i < size; i++) {
// some code goes here
}
We can do iterations with following recursive function:
private void iterate(int i, int size) {
if (i == size){
return;
}
// some code goes here
iterate(i+1, size);
}
And starting call would be:
iterate(0, size);
That would execute some code for every i 0..size.
This problem can actually be solved without the use of an additional method. The concept is as follows:
if list is empty return 0
if list has 1 item and it is <= limit return item
if list has 1 item and it is > limit return 0
if list has more than 1 item and first item is > limit return the max of sublist
otherwise return the max between max of sublist and first item plus max of sublist with limit minus the first item
public static int maxSum(List<Integer> numbers, int limit) {
if(numbers.size() == 0){ return 0; }
int num = numbers.get(0);
if(numbers.size() == 1){
if(num > limit){
return 0;
}else{
return num;
}
}
List<Integer> sublist = numbers.subList(1, numbers.size());
int subMax = maxSum(sublist, limit);
if(num > limit){ return subMax; }
int max = num + maxSum(sublist, limit - num);
return Math.max(max, subMax);
}
Based on #Deximat 's suggestion, I rewrite the code to remove the for loop, and it works!
public static int maxSum2(List<Integer> L, int limit){
boolean[] used = new boolean[L.size()];
int[] max = {0};
rec2(L, limit, 0, used, max, 0);
return max[0];
}
public static boolean rec2(List<Integer> L, int limit, int cur, boolean[] used, int[] max, int index){
if(cur > limit){
return false;
}
if(index == L.size()){
return true;
}
if(!used[index]){
used[index] = true;
if(rec2(L, limit, cur+L.get(index), used, max, index)){
max[0] = Math.max(max[0], cur+L.get(index));
// return true;
}
used[index] = false;
}
return rec2(L, limit, cur, used, max, index+1);
}
I was interviewed a problem and after that I tested my code, found it wrong.
Not good at recursion. But I can't figure out the problem.
The question is: Given an array range from 0 ~ 9, and a length, for example, 3; generate
all permutations of integers from the given array in given length.
So, for the example:
The permutation should be: 012, 013, 014,..., 345, 346...
Below is my java code, where's the problem? (I think it's the index or the offset part)
And, if there's any better solution!
public void NumPermutation(int[] list, int offset, int[] temp, int index){
if(index == 4){
printarray(temp);
}
for(int count = offset; count < list.length; count++){
temp[index++] = list[count];
int te = list[offset];
list[offset] = list[count];
list[count] = te;
NumPermutation(list, offset, temp, index);
index -= 1;
}
}
public void test(int len){
int[] list = {0,1,2,3,4,5,6,7,8,9};
int[] temp = new int[4];
int index = 0, offset = 0;
NumPermutation(list, offset, temp,index);
}
The problem is that, the offset may increase each time and
it can't even reach the number to the end.
You need to:
Pass offset+1 to the recursive call.
Return in the if-statement.
Reverse your swap after the recursive call.
Replace the 4 with temp.length for a more generic solution.
Also preferably replace index++, index, index -= 1 with index, index + 1 and nothing.
Which results in this code: (replaced printarray with a standard print method, assuming this is Java)
public static void NumPermutation(int[] list, int offset, int[] temp, int index){
if(index == temp.length) {
System.out.println(Arrays.toString(temp));
return;
}
for(int count = offset; count < list.length; count++){
temp[index] = list[count];
// swap
int te = list[offset];
list[offset] = list[count];
list[count] = te;
NumPermutation(list, offset + 1, temp, index + 1);
// reverse swap
te = list[offset];
list[offset] = list[count];
list[count] = te;
}
}
Live demo.
I read through all subset sum topics and still have issues with implementing the algorithm for the following problem.
Given the array A of N integers (N<=20) where
a[i]<=20
values do not have to be unique
and an integer K (K<=20).
Rules:
Array items equal to K are "covered" with K.
If sum of two or more array numbers is equal to K, these numbers are also covered.
Each number in the array can be covered only once.
Example:
N=6, integers: 1, 1, 2, 3, 4, 5
K=4
Possible coverages:
coverage
4 is covered.
1, 1, 2 are covered as 1+1+2=4.
coverage
4 is covered.
1, 3 are covered as 1+3=4.
K=5
Possible coverages:
coverage
5 is covered.
1,1,3 are covered as 1+1+3=5.
coverage
5 is covered.
1,4 are covered as 1+4=5.
2,3 are covered as 2+3=5.
Goal:
For given array A and integer K, find all possible "coverages". I need all coverages, not only one which covers most of the array items.
I have tried with two approaches:
Brut force algorithm.
Checking all possible subsets of all possible sizes works, but takes too much time even for only 10 numbers. I need it to finish in no more than 500ms.
First, I sorted the array in descending order. Then for each possible number of sub-sums I create "slots". I loop through the array and put numbers in the slots following the rules like:
Put number in the slot if its sum becomes equal to K.
Put number in the slot having the least sum of all slots.
Put number in the slot which gives the closet sum to K of all slots.
Well, the second approach works and works fast. But I found scenarios where some coverages are not found.
I would appreciate if somebody offered idea for solving this problem.
I hope I explained the problem well.
Thanks.
I don't have ready answer for that, but I recommend to take a look on 'Bin packing problem' it could be usefull here.
The main problem is to find all possible sums giving number K. So try this:
Collection All_Possible_Sums_GivingK;
find_All_Sums_Equal_To_K(Integer K, Array A)
{
/* this function after finding result
add it to global Collection AllPossibleSumsGivingK; */
find_All_Elements_Equal_To_K(Integer K, Array A);
Array B = Remove_Elements_Geater_Or_Equal_To_K(Integer K, Array A);
for all a in A {
find_All_Sums_Equal_To_K(Integer K-a, Array B-a)
}
}
I modified this from an earlier answer I gave to a different subset sum variant: https://stackoverflow.com/a/10612601/120169
I am running it here on the K=8 case with the above numbers, where we reuse 1 in two different places for one of the two "coverages". Let me know how it works for you.
public class TurboAdder2 {
// Problem inputs
// The unique values
private static final int[] data = new int[] { 1, 2, 3, 4, 5 };
// counts[i] = the number of copies of i
private static final int[] counts = new int[] { 2, 1, 1, 1, 1 };
// The sum we want to achieve
private static int target = 8;
private static class Node {
public final int index;
public final int count;
public final Node prevInList;
public final int prevSum;
public Node(int index, int count, Node prevInList, int prevSum) {
this.index = index;
this.count = count;
this.prevInList = prevInList;
this.prevSum = prevSum;
}
}
private static Node sums[] = new Node[target+1];
// Only for use by printString and isSolvable.
private static int forbiddenValues[] = new int[data.length];
private static boolean isSolvable(Node n) {
if (n == null) {
return true;
} else {
while (n != null) {
int idx = n.index;
// We prevent recursion on a value already seen.
// Don't use any indexes smaller than lastIdx
if (forbiddenValues[idx] + n.count <= counts[idx]) {
// Verify that none of the bigger indexes are set
forbiddenValues[idx] += n.count;
boolean ret = isSolvable(sums[n.prevSum]);
forbiddenValues[idx] -= n.count;
if (ret) {
return true;
}
}
n = n.prevInList;
}
return false;
}
}
public static void printString(String prev, Node n, int firstIdx, int lastIdx) {
if (n == null) {
printString(prev +" |", sums[target], -1, firstIdx);
} else {
if (firstIdx == -1 && !isSolvable(sums[target])) {
int lidx = prev.lastIndexOf("|");
if (lidx != -1) {
System.out.println(prev.substring(0, lidx));
}
}
else {
while (n != null) {
int idx = n.index;
// We prevent recursion on a value already seen.
// Don't use any indexes larger than lastIdx
if (forbiddenValues[idx] + n.count <= counts[idx] && (lastIdx < 0 || idx < lastIdx)) {
// Verify that none of the bigger indexes are set
forbiddenValues[idx] += n.count;
printString((prev == null ? "" : (prev + (prev.charAt(prev.length()-1) == '|' ? " " : " + ")))+data[idx]+"*"+n.count, sums[n.prevSum], (firstIdx == -1 ? idx : firstIdx), idx);
forbiddenValues[idx] -= n.count;
}
n = n.prevInList;
}
}
}
}
public static void main(String[] args) {
for (int i = 0; i < data.length; i++) {
int value = data[i];
for (int count = 1, sum = value; count <= counts[i] && sum <= target; count++, sum += value) {
for (int newsum = sum+1; newsum <= target; newsum++) {
if (sums[newsum - sum] != null) {
sums[newsum] = new Node(i, count, sums[newsum], newsum - sum);
}
}
}
for (int count = 1, sum = value; count <= counts[i] && sum <= target; count++, sum += value) {
sums[sum] = new Node(i, count, sums[sum], 0);
}
}
printString(null, sums[target], -1, -1);
}
}
I came across this question in one Interview. Please help me in getting the solution.
Question is:
You have sorted rotatable array, i. e. the array contains elements which are sorted and it can be rotated circularly, like if the elements in array are [5,6,10,19,20,29] then rotating first time array becomes [29,5,6,10,19,20] and on second time it becomes [20,29,5,6,10,19] and so on.
So you need to find the smallest element in the array at any point. You won’t be provided with number times array is rotated. Just given the rotated array elements and find out the smallest among them. In this case output should be 5.
Method 1:
You can do this in O(logN) time.
Use a modified binary search to find the point of rotation which is an index i such that arr[i] > arr[i+1].
Example:
[6,7,8,9,1,2,3,4,5]
^
i
The two sub-arrays (arr[1], arr[2], .., arr[i]) and (arr[i+1], arr[i+2], ..., arr[n]) are sorted.
The answer is min(arr[1], arr[i+1])
Method 2:
When you split the sorted, rotated array into two halves (arr[1],..,arr[mid]) and (arr[mid+1],..,arr[n]), one of them is always sorted and the other always has the min. We can directly use a modified binary search to keep searching in the unsorted half
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
The above algorihtm fails if data element is repeated like {8,8,8,8,8} or {1,8,8,8,8} or {8,1,8,8,8} or {8,8,1,8,8} or {8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
To Find the smallest number in the sorted rotated array:
using Binary search concept
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
But if you don't want to use Binary Search, then :
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
Here is the code in Python:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
My code is below with the algorithm as comments. Works even for the repeated elements.
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
This can be done in O(1) time best case, O(n) time worst case, and O(lg n) time on average.
For a rotated sorted array, if the first element in the array is less than the last element in the array, then the sorted array is not rotated (or rotated 0 position). The minimum element is simply the first element.
If the middle element is less than the last element, then the minimum element is in [first, middle].
If the middle element is greater than the last element, then the minimum element is in [middle + 1, last].
If the middle element is equal to the last element, then there are two sub-cases:
the first element is larger than the last element, in which case the minimum element is in [first, middle + 1];
the first element is equal to the last element, in which case it is inconclusive to reject either half of the array. Reduce to linear search. For example, for arrays such as [5,5,5,1,5] and [5,1,5,5,5], it is impossible by just examining the first, last and middle element (since they are all equal) which half of the array the minimum element lies.
I wrote the following code in C++ to solve this problem, which should handle all cases (empty array, repeated elements).
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
Find Min index in circular sorted array
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
In case any one needs it.. My implementation in java..
takes care of sorted/unsorted ascending//descending order usecases..
drawback is it will still perform log n steps to find min value in a perfectly sorted set with no rotation.
http://ideone.com/fork/G3zMIb
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
Errors/suggestions/failed usecases are welcomed
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
The following algorithm takes log(n) time. Assuming the array has no duplicate.
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
I did it using a slightly modified version of binary search. What I am doing here is I keep going left or right based on where the minimum could be. For example in an ascending array if the mid element is less than the left most element, its possible that the minimum is to the left. While recursing thru the array, I also keep track of the minimum. The recursion continues until the end and then the latest min is returned. This also works with repeated elements.
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
Question : Find minimum in a sorted rotated array .
Solution 1 : Using Binary Search
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
first if statement checks if even array is rotated at all. in that case first element is the min . if length of list is 1 then that element is min.
else if mid element is less than last element then continue to look in second half else look for the element in first half
//java program to find minimum element in a sorted array rotated
//about any pivot in O(log n) in worst case and O(1) in best case
class ArrayRotateMinimum {
public static void main(String str[]) {
// initialize with your sorted rotated array here
int array[] = { 9, 1, 2, 3, 4, 5, 6, 7, 8, };
System.out.println("Minimum element is: " + minimumElement(array));
}
static int minimumElement(int array[]) {
// variables to keep track of low and high indices
int low, mid, high;
// initializing variables with appropriate values
low = 0;
high = array.length - 1;
while (low < high) {
// mid is always defined to be the average of low and high
mid = (low + high) / 2;
if (array[low] > array[mid]) {
// for eg if array is of the form [9,1,2,4,5],
// then shift high to mid to reduce array size by half
// while keeping minimum element between low and high
high = mid;
} else if (array[mid] > array[high]) {
// this condition deals with the end case when the final two
// elements in the array are of the form [9,1] during the
// last iteration of the while loop
if (low == mid) {
return array[high];
}
// for eg if array is of the form [4,5,9,1,2],
// then shift low to mid to reduce array size by half
// while keeping minimum element between low and high
low = mid;
} else {
// the array has not been rotated at all
// hence the first element happens to be the smallest element
return array[low];
}
}
//return first element in case array size is just 1
return array[0];
}
}
This is my pythonic solution using recursion:
Time complexity is O(log(n)) & Space complexity: O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
Here is a very simple answer, it will work for all test cases:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
Solution for both array with duplicate and not, with the recursive binary search approach.
Unique array
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
Array with duplicates
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};