Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
3
of 7 vote

Can you explain why your example "987"->"1023" violate the rule 3?

- Mem March 10, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Thanks. But,if '0'>'2' and '0'>'3', this is still not valid.

- Mem March 10, 2014 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 votes

I had a second thought. assuming 0 being the first digit doesn't make sense in this question because this way 0 cannot appear in any integer. So, 0 is the last digit in two scenarios:
1) input-> 789, output->790
2) input-> 987, output->1023
Let me know if this makes sense to you.

- Obiwana March 10, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Still the question exists, if '0' is the last digit, it is larger than '2' and '3'. 2) input-> 987, output->1023 this scenario is not valid.

- Mem March 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
4
of 4 votes

Did you met this question in the interview or saw some place else?

- Mem March 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

My guess 0 is not considered for comparison. So we can use it at any position.

- kr.neerav March 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The only integer which goes by all rule is 1234 (not 1023 as mentioned by the author of this question).

- PUdayakumar July 13, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

Assume:
"input=987, return=1023" is a wrong example, which violates the rule 3.

A brute-force algorithms:
Define Two Helper Data Array:
MAX_Data_Helper = { 0, 9, 89, 789, 6789, 56789, 456789, 3456789, 23456789, 123456789 };
MIN_Data_Helper = { 0, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, -1 };

Algorithm is shown below: Given a number: n
Case 1: If n is negative, return 0;
Case 2: If n is >= 123456789, then there is no solution;
Case 3: Otherwise, n is in [0, 123456789) [for example: n = 321]
3.1: Find the minimum upper bound in MAX_Data_Helper. [It is 789]
3.2: If n < 123, then return 123. [gets 123 from MAX_Data_Helper]
Otherwise, brute-check all numbers from n+1 to minimum upper bound. [In this case, check from 322 to 789]
3.3: the three rules in together means (lower sinificant degit > higher sinificant degit).

Performance Analysis:
Ignore negative numbers and very large numbers > 123456789.
Assume numbers are uniformly random in [0, 123456789).
Then, most numbers get Big-O: O(1). For example, for numbers in [56789, 123456), return 123456 immediately.
As n goes larger, the precentage of numbers with O(1) is larger. So, the amortized cost is O(1).
But the worst case performance is very bad. for example, if n = 23456789, it is costly to find the next.

- xuyan.nus May 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Good Logic. You named it "brute-force" because of the step 3.2. In fact the step 3.2 can be optimized easily.

The logic is:
Say the length of the number is k.
The number: [1][2][3][4][5][..][k]

Loop the array and each digit in the solution should satisfy:
1) s[i] > s[i-1]
2) s[i] >= n[i] (if the pre-fix are the same between s and n)
(s means solution and n mean the original number)

The only problem is that s might equals to n.
Then, increase 1 at the lower significance digit.
for example:
128 -> 129.
129 -> 134. (since 9 cannot increase, has to increase 2)

However, the final code is still pretty complex. Not easy to read by others.

- xyz May 07, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

private static int getInteger(int input)
{
int rem1;
int rem2;
boolean found = false;
HashSet<Integer> set;

if(input < 0)
{
return 0;
}
else if(input/10 == 0)
{
return input+1;
}
else
{
while(!found)
{
found = true;
int temp = input;
set = new HashSet<Integer>();
rem1 = -1;
rem2 = -1;
System.out.println("INPUT: "+temp);
while(temp != 0)
{
rem1 = temp % 10;
temp = temp / 10;

if(!set.add(rem1) || (rem2 != -1 && rem2 < rem1))
{
found = false;
break;
}
rem2 = rem1;
}

if(found)
{
break;
}
else
{
input++;

}
}

return input;
}
}

- Gagan Mani March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This is pure brute force. I am wondering if there is any better way to solve the problem.

- ravio May 25, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

The following code works fine, tested:

private static int getInteger(int input)
{
int rem1;
int rem2;
boolean found = false;
HashSet<Integer> set;

if(input < 0)
{
return 0;
}
else if(input/10 == 0)
{
return input+1;
}
else
{
while(!found)
{
found = true;
int temp = input;
set = new HashSet<Integer>();
rem1 = -1;
rem2 = -1;
System.out.println("INPUT: "+temp);
while(temp != 0)
{
rem1 = temp % 10;
temp = temp / 10;

if(!set.add(rem1) || (rem2 != -1 && rem2 < rem1))
{
found = false;
break;
}
rem2 = rem1;
}

if(found)
{
break;
}
else
{
input++;

}
}

return input;
}
}

- gaganmani90 March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Assuming input is a positive integer, following is code in C++:

bool nextInteger(string& res, int i, const string& src, bool used[], bool alreadyLarger)
{
	if(i == src.size()) return src < res;
	if(alreadyLarger){//set every position left with smallest integer not used
		int k = 0;
		for(; i < src.size(); ++i){
			for(; k < 10; ++k){
				if(!used[k]){
					res[i] = '0' + k++;
					break;
				}
			}
		}
		return true;
	}
	
	for(char c = src[i]; c <= '9'; ++c){
		if(used[c - '0']) continue;
                res[i] = c;
		used[c - '0'] = true;
		if(nextInteger(res, i + 1, src, used, c > src[i])) return true;
		used[c - '0'] = false;
	}
	return false;
}
string nextInteger(const string& input)
{
	static const string limit[11] = {
		"",
		"9",
		"98",
		"987",
		"9876",
		"98765",
		"987654",
		"9876543",
		"98765432",
		"987654321",
		"9876543210",
	};

	int len = input.size();
	if(len > 10 || len == 10 && limit[10] <= input) return "";//no such number

	string res;
	if(limit[len] <= input){//result is smallest with length = input.length + 1
		res.resize(len + 1);
		res[0] = '1';
		res[1] = '0';
		for(int i = 2; i <= len; ++i){
			res[i] = i + '0';
		}
	}
	else{//get next larger with length = input.length
		res.resize(len);
		bool used[10] = {0};
		nextInteger(res, 0, input, used, false);
	}
	return res;
}

- uuuouou March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your limit[] is incorrect.

if the first digit is greater than 10-len,
say
9*,
8**,
7***,
6****,
....
should jump to brunch

if(limit[len] <= input)

- Tuotuo March 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Any input with > 10 characters will definitely have a repeated character - why? (pigeon hole principle)
Any input with 10 characters also will not have a valid solution - why? because for 10 characters we need to include 0-9, in increasing order which means 0 has to be at the beginning which makes it a 9 digit integer.
Any input with 9 digits can have 2 different solutions:
if input is < 123456789 then answer is 123456789
else no solution
similarly we can solve other cases - should be trivial.

- Anon March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It is not saying you should use all the integers.

- Bayraktar.Eralp March 12, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class IncrementString {

	public static String nextString(String num) {
		char[] numArr = num.toCharArray();

		boolean canBeIncrementedWithinTheSameNumberOfDigit = true;

		for (int i = 0; i < numArr.length; i++) {

			if ((10 - (numArr[i] - '0')) < (numArr.length - 1 - i)) {
				canBeIncrementedWithinTheSameNumberOfDigit = false;
				break;
			}

		}

		if (canBeIncrementedWithinTheSameNumberOfDigit) {

			for (int i = 0; i < numArr.length; i++) {
				numArr[i] = ++numArr[i];
			}
			return new String(numArr);

		} else {
			char[] newNumArr = new char[numArr.length + 1];
			for (int i = 0; i <= numArr.length; i++) {
				newNumArr[i] = (char) ('0' + (i + 1));
			}

			return new String(newNumArr);
		}

	}

	public static void main(String[] args) {
		System.out.println(nextString("978"));
	}
}

- Anonymous March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Unless I'm missing something, I also agree that 1023 seems to violate the rule requiring an incremental sequence of numbers. If that's true, then it seems to me that the entire set of valid numbers would be (in their string representation) sub-strings of either of the following:

"9876543210"
"123456789"

That means there are only 100 valid numbers: sum(i=1...9: i) + sum(j=1...10: j) = (9*9 + 9)/2 + (10*10 + 10)/2 = 45 + 55 = 100. That means they can all easily fit into memory of any reasonable device today and calculating them all should be fast as well. Store the calculated values in a map of seq_i -> seq_(i+1) and lookup will be trivial. Brute force, I know, but it seems like a reasonable trade off for O(1) evaluation. If something more general is required, it is still possible to generate the subset of possible numbers based off of the position in the string. However, as I was trying that approach, it just seemed like there was way too many logic forks.

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.util.Collections;
import java.util.List;
import java.util.Map;

class GoogleIntSequence {
    private static final String seq =    "123456789";
    private static final String revSeq = "9876543210";
    private static Map<String, String> nextMap;

    static {
        nextMap = Maps.newHashMap();
        List<Long> allVals = Lists.newArrayList();
        for (int i = 0; i < revSeq.length(); ++i) {
            for (int j = i+1; j <= revSeq.length(); ++j) {
                if (j <= seq.length()) {
                    allVals.add(Long.parseLong(seq.substring(i, j)));
                }
                allVals.add(Long.parseLong(revSeq.substring(i, j)));
            }
        }

        Collections.sort(allVals);
        for (int i = 0; i < allVals.size() - 1; ++i) {
            nextMap.put(allVals.get(i).toString(), allVals.get(i+1).toString());
        }
    }

    public static String findNextSequence(String s) {
        if ("9876543210".equals(s)) {
            throw new IllegalArgumentException("Last valid number input");
        }
	
        if (!nextMap.containsKey(s)) {
            throw new IllegalArgumentException("Input integer not well formed.");
        }

        return nextMap.get(s);
    }
}

- M March 12, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I like your idea, but we have to make sure that "incremental" does not mean increasing, because we will have a lot of valid number like 13,18,269,2568 and so on. Also, can it be decremental? I do not understand why you need all sub-sequences of "9876543210"

And finally your solution need to be fixed, because it does not work for any input. As I understand input Integer number can be ANY number.
simple solution will be:
- store all 45 valid numbers in sorted order
- binary search input number
- if you find it return next one, otherwise return next greater(you will find possible insertion point in any case)

Memory is Constant, and time complexity is also O(1) - as it is just log 45 ~ 6 comparisons

- Alex March 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Best approach in my opinion is (assuming the number can't be more than 10^10):

Add the following numbers into a sorted list, prefixing a particular sequence,
1
12
123
...
123456789

Then start with 2:
2
23
234
2345
...
2345678901

so on

Finally, do a binary search on the sorted array and find the next biggest element.

- Brave Heart March 15, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Array will have 1000 elements.
Complexity is O(1000) space, binary search O(log(1000)) ~ 10

- Brave Heart March 15, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think you should also add 1 3, 1 4, 1 2 3, 1 3 4 and so on. Then you do binary search.

- ravio May 25, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include <iostream>
#include <stdlib.h>

bool nodup_digit(int x)
{
  int a[10] = {0};

  while (x > 0)
  {
    int d = x % 10;
    a[d] = a[d] + 1;
    if (a[d] > 1)
      return false;
    x /= 10;
  }

  return true;
}

bool increment(int x)
{
  int max = 9;

  while (x > 0)
  {
    int d = x % 10;
    if (d > max)
      return false;

    max = d;
    x /= 10;
  }

  return true;
}

int next(int n)
{
  if (n < 0)
    return 1;

  ++n;

  while (!nodup_digit(n) || !increment(n))
  {
    ++n;
  }

  return n;
}

int main(int argc, char* argv[])
{
  int x = atoi(argv[1]);
  std::cout << next(x) << "\n";
  return 0;
}

- Anonymous March 17, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

assuming the maximum we can get is '123456789', so it's invalid for input bigger than '123456788'
then we plus the input by 1, so we can check our generated result by greater or equal function.
first we generate the biggest valid number we could have for the length of input, e.g 899 as input, the biggest is 789
if it's smaller than input+1, simply return 1234, as we know it's the smallest valid result.
if for input 688, the maximum 789 is bigger than it, so we scrimp it from the highest bit.

time complexity is (n^2) which n is the length of input string, space complexity is n.

#include <vector>

template<typename T>
bool _ge(const T &str_1, const string &str_2) {
  if (str_1.size() > str_2.size()) return true;
  if (str_1.size() < str_2.size()) return false;
  if (str_1.size() == str_2.size()) {
    for (int i = 0; i < str_1.size(); ++i) {
      if (str_1[i] < str_2[i]) return false;
      if (str_1[i] > str_2[i]) return true;
    }
  }
  return true;
}

string* nextInteger(const string& input_0) {
  // valid input should not greater than 123456788
  if (!_ge(string("123456788"), input_0)) return NULL;
  // plus the input by one
  string input(input_0);
  for (int i = input.size() - 1; i >= 0; --i) {
    if (input[i] == '9') {
      input[i] = '0';
      if (i == 0) {
        input = "1" + input;
      }
    } else {
      input[i] += 1;
      break;
    }
  }
    
  vector<char> buffer;
  // construct a string of the maximum for the same length.
  for (int i = input.size() - 1; i >= 0; --i) {
    buffer.push_back('9' - i);
  }
  // the next greater one needs extra significant bit.
  if (!_ge(buffer, input)) {
    string *next = new string(input.size() + 1, '0');
    for (int i = 0; i <= input.size(); ++i) {
      (*next)[i] += i + 1;
    }
    return next;
  }
  // the next greater one doesn't need extra significant bit.
  char prev = input[0];
  int i = 0;
  for (; i < input.size(); ++i) {
    // choose the bigger one, the previous bit + 1 or the input bit.
    buffer[i] = prev > input[i]? prev: input[i];
    if (!_ge(buffer, input)) {
      // if we found the current number is lower than the input one, increase
      // current bit by 1
      buffer[i] += 1;
      ++i;
      break;
    }
    prev = buffer[i] + 1;
  }
  for (; i < input.size(); ++i) {
    // since previous bit has been increased by 1, the smaller one for the rest
    // bits will just increase 1 each.
    buffer[i] = buffer[i - 1] + 1;
  }
  string *next = new string(buffer.size(), '0');
  for (int i = 0; i < buffer.size(); ++i) (*next)[i] = buffer[i];
  return next;
}

- Deo March 20, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think this covers all cases. =)

public int nextInteger(String input) {
		int in = Integer.parseInt(input);
		String nums = "123456789"; // will be used as a sliding substring window
		int length = input.length();
		// find the corresponding index in nums from first character of input.
		int firstCharIndex = Integer.parseInt(input.charAt(0) + "") - 1; 
		int lastCharIndex = firstCharIndex + (length - 1); // expected last index of the sliding window
		int i = 0;
		int j = length - 1;
		
		// invalid if 9 or more digits
		if(length >= 9)
			return -1;
		
		if(in <= 0)
			return 1;
		
		// overflow to next digit if the expected last index constructed is greater nums' length
		if(lastCharIndex > nums.length() - 1) {
			j = length;
			return Integer.parseInt(nums.substring(i, j + 1));
		}
		
		// compare the input with a sliding window of nums of the same length.
		while(j < nums.length()) {
			int checkNum = Integer.parseInt(nums.substring(i, j + 1));
			// return when sliding window is larger than the input
			if(checkNum > in)
				return checkNum;
			
			i++;
			j++;
		}
		
		return -1;
		
	}

- Peter March 24, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry. The first check should be:

if(length > 9)
	return -1;

- Peter March 24, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi,
This is a nice solution but it won't work inputs such as: 799, 125,...

- Bhumik September 17, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class NextAscendingPositive {

	public static String nextInteger(String num){
		int n = num.length();
		if(n <= 0 || n >= 9) return null;

		int prev = 0;
		int i;
		for(i = 0; i < n; i++){
			int digit = num.charAt(i) - '0';
			// check blocker

			if(digit <= prev){
				return num.substring(0,i)+createSequence(prev+1, n-i);
			}

			if(digit + n-i-1 > 9) {
				break;
			}

			prev = digit;		
		}

		String ret = null;
		if(i >= n){ // blocker not found
			ret = createSequence((int)(num.charAt(0)-'0'+1), n);
			if(ret == null) {
				ret =  createSequence(1, n+1);
			}
		} else {
			for(i = i-1; i >=0; i--){
				int digit = num.charAt(i) - '0'+1;
				if(digit + n-i-1 <= 9)  {
					ret = num.substring(0,i)+createSequence(digit, n-i);
					break;
				}	
			}
			if(ret  == null){
				ret = createSequence(1, n+1);
			}

		}

		return ret;
	}


	private static String createSequence(int startDigit, int nDigs){
		if(startDigit+nDigs > 10) return null;
		StringBuilder sb = new StringBuilder();
		for(int  i = 0; i < nDigs; i++){
			sb.append(startDigit++);
		}
		return sb.toString();
	}

	
	public static void main(String[] args) {
		int num = 34234;
		test(num);
		test(12345);
		test(93245);
		test(985);
		test(67234);
		test(6723);
		test(123458769);
		
	}


	private static void test(int num) {
		System.out.println("Next of '"+ num+ "' is " + nextInteger(String.valueOf(num)) );
	}
	
}

- konst May 24, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package google;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class NextIntWithUniqueDigits {
    @Test
    public void test() {
        assertEquals("1", nextInt("0"));
        assertEquals("124", nextInt("000123"));
        assertEquals("124", nextInt("123"));
        assertEquals("134", nextInt("132"));
        assertEquals("234", nextInt("191"));
        assertEquals("345", nextInt("298"));
        assertEquals("1234", nextInt("987"));
        assertEquals("1234", nextInt("789"));
        assertEquals("1567", nextInt("1543"));
        assertEquals("45678", nextInt("41543"));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBig() {
        nextInt("123456789");
    }

    @Test(expected = IllegalArgumentException.class)
    public void testEmpty() {
        nextInt("");
    }

    public static String nextInt(String previous) {
        if (!previous.matches("\\d+")) {
            throw new IllegalArgumentException("Argument should contain at least one digit and no other characters.");
        }

        previous = trimLeadingZeros(previous);

        if (previous.equals("0")) {
            return "1";
        }
        if (previous.length() > 9 || Integer.valueOf(previous) >= 123456789) {
            throw new IllegalArgumentException(String.format("No next integer available for %s.", previous));
        }

        char[] chs = new char[previous.length() + 1];
        chs[0] = '0';
        System.arraycopy(previous.toCharArray(), 0, chs, 1, previous.length());

        modifyToNextInt(chs);

        if (chs[0] == '0') {
            return new String(chs, 1, chs.length - 1);
        } else {
            return new String(chs);
        }
    }

    private static String trimLeadingZeros(String str) {
        int nonLeadingZeroChar = 0;
        while (str.charAt(nonLeadingZeroChar) == '0' && nonLeadingZeroChar != str.length() - 1) {
            nonLeadingZeroChar++;
        }
        if (nonLeadingZeroChar > 0) {
            return str.substring(nonLeadingZeroChar);
        } else {
            return str;
        }
    }

    private static int findDigitLessThenPrevious(char[] chs) {
        int idx = 1;
        while (idx < chs.length - 1 && chs[idx] > chs[idx - 1]) {
            idx++;
        }
        return idx;
    }

    private static int findDigitToChangeFrom(char[] chs) {
        int idx = findDigitLessThenPrevious(chs);
        while (idx > 0 && ('9' - (Math.max(chs[idx], chs[idx - 1]) + 1)) < chs.length - idx) {
            idx--;
        }
        return idx;
    }

    private static void modifyToNextInt(char[] chs) {
        int d = findDigitToChangeFrom(chs);
        if (d == 0) {
            chs[d] = '1';
        } else {
            chs[d] = (char) (Math.max(chs[d], chs[d - 1]) + 1);
        }
        for (int i = d + 1; i < chs.length; i++) {
            chs[i] = (char) (chs[i - 1] + 1);
        }
    }
}

- Marboni July 12, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Assuming 1023 is not valid and instead the answer is 1234, observe the following.
if Input.length() == 0 || Input.length() > 10 then it won't work...

take the first digit of the input, and increment the first digit to get the next digits.
i.e. Input = 2xxx, output = 2345.
It can easily be seen that this is the optimal solution, as every other number starting with 2 smaller than 2345 will have either duplicates, or violate the increasing sequence rule.

This won't work if we need to roll-over. easy way to check for roll-over is if Input.length() > 10 - firstDigit.
if it's rolled over then it's even simpler, just make a 1234... sequence with length = 1 + Input.length()

- aleck.yd.wu September 12, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int getNextNumber( int number ) {
         if( number >= Integer.MAX_VALUE)
            return -1;

         if( number > -1 && number < 9 ) {
            return number+1;
         }
         number++;
         String word = Integer.toString(number);
         char[] digits = word.toCharArray();
         if( !isUnique( digits) || !isIncremental(digits) )
            return getNextNumber(number);
         return number;

   }

   private boolean isUnique( char [] digits ) {
     HashSet<Character>set = new HashSet<Character>();
     for( char c : digits ){
       if ( set.contains(c) ) return false;
       else
          set.add(c);
     }
     return true;
   }


   private boolean isIncremental(char [] digits ) {

      int prev = -1;
      for(char c : digits ) {
         if (prev > Character.getNumericValue(c))
            return false;
         prev = Character.getNumericValue(c);
      }
     return true;
  }

- Rohit November 20, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int getNextNumber( int number ) {
         if( number >= Integer.MAX_VALUE)
            return -1;

         if( number > -1 && number < 9 ) {
            return number+1;
         }
         number++;
         String word = Integer.toString(number);
         char[] digits = word.toCharArray();
         if( !isUnique( digits) || !isIncremental(digits) )
            return getNextNumber(number);
         return number;

   }

   private boolean isUnique( char [] digits ) {
     HashSet<Character>set = new HashSet<Character>();
     for( char c : digits ){
       if ( set.contains(c) ) return false;
       else
          set.add(c);
     }
     return true;
   }


   private boolean isIncremental(char [] digits ) {

      int prev = -1;
      for(char c : digits ) {
         if (prev > Character.getNumericValue(c))
            return false;
         prev = Character.getNumericValue(c);
      }
     return true;
  }

- Rohit November 20, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Basically there are two cases: a. ending with consecutive series of numbers '...6789'; b. start from '123...' if number can't be covered with case a).

public void Test()
        {
            Debug.Assert(124 == GetNumber(000123), "Test [000123] failed");
            Debug.Assert(123 == GetNumber(122), "Test [123] failed");
            Debug.Assert(134 == GetNumber(132), "Test [132] failed");
            Debug.Assert(234 == GetNumber(222), "Test [222] failed");
            Debug.Assert(345 == GetNumber(298), "Test [298] failed");
            Debug.Assert(1234 == GetNumber(789), "Test [789] failed");
            Debug.Assert(1234 == GetNumber(987), "Test [987] failed");
            Debug.Assert(1567 == GetNumber(1543), "Test [1543] failed");
            Debug.Assert(3456 == GetNumber(3333), "Test [3333] failed");
            Debug.Assert(6789 == GetNumber(6788), "Test [6788] failed");
            Debug.Assert(1469 == GetNumber(1468), "Test [1468] failed");
            Debug.Assert(1567 == GetNumber(1543), "Test [1543] failed");
            Debug.Assert(45678 == GetNumber(41543), "Test [41543] failed");
            Debug.Assert(134567 == GetNumber(127777), "Test [127777] failed");
        }

        private int GetNumber(int number)
        {
            int[] digits = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            // check if number below possible limit
            const int maxNumber = 123456789;
            if (number >= maxNumber)
            {
                throw new Exception(string.Format("Too big number [{0}]", number));
            }

            // negative number produce 0 result
            if (number < 0)
            {
                return 0;
            }

            string numberString = number.ToString(CultureInfo.InvariantCulture);
            int length = numberString.Length;
            int[] numberDigits = numberString.ToCharArray().Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();

            List<int> resultDigits = new List<int>(length);

            int prevDigit = 0;
            for (int index = 0; index < length; index++)
            {
                int digit = numberDigits[index];

                // if the digit becomes lower than previous one => skip
                bool mayTakeDigit = prevDigit < digit;

                if (mayTakeDigit && 10 < digit + length - index)
                {
                    // if there is no room for reminder of a kind '...56789' => skip
                    mayTakeDigit = false;
                }

                if (mayTakeDigit)
                {
                    int maxIndexNumber = 0;
                    for (int i = 0; i <= index; i++)
                    {
                        maxIndexNumber += (int)Math.Pow(10, length - 1 - i) * numberDigits[i];
                    }

                    for (int i = 0; i < length - index - 1; i++)
                    {
                        maxIndexNumber += (int)Math.Pow(10, i) * digits[8 - i];
                    }

                    // if there is no enough room of a number of kind (i.e. number > 'xxx56789') => skip
                    mayTakeDigit = number < maxIndexNumber;
                }
                else
                {
                    digit = prevDigit;
                }

                if (mayTakeDigit)
                {
                    resultDigits.Add(index == length - 1 ? 9 : digit);
                }
                else
                {
                    // get consecutive range starting from 'digit + 1'
                    if (index <= length - 1)
                    {
                        if (digit > 0 && digit + length - index < 10)
                        {
                            // if not overcome 10 then finish with '...56789'
                            for (int i = 0; i < length - index; i++)
                            {
                                resultDigits.Add(digit + 1 + i);
                            }
                        }
                        else
                        {
                            // start from '12345...'
                            digit = 0;
                            for (int i = 0; i < length + 1; i++)
                            {
                                resultDigits.Add(digit + 1 + i);
                            }
                        }
                    }

                    break;
                }

                prevDigit = digit;
            }

            int resultNumber = 0;
            for (int i = 0; i < resultDigits.Count; i++)
            {
                resultNumber += (int)Math.Pow(10, resultDigits.Count - 1 - i) * resultDigits[i]; ;
            }

            return resultNumber;
        }

- Dmitry November 25, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

NextNumber(int number)
{
  int numbDigits = numberofdigits(n);
  int [] digits = GetDigits(N+1);
  if(digits.length >9) return -1;
  int default = 123456789;
  bool isdefault = false;
  for(int i=0;i<digits.length ;i++)
  {
    if(9-digits[i]<=digits.length-i-1) { isdefault = true; break;}
    if(i>0 and digits[i]<digits[i-1]) digits[i] = digits[i-1] + 1;
  }
  if(isdefault) return default/(10^(numberofdigits+1))
  else converttonumber(digits);
}

- aditya.eagle059 February 08, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

O(d) solution in the number of digits, which is limited to 10 due to int representation limits, so O(1) solution.

int next_larger_asc(int num)
{
    if (num <= 0) return 1;
    int t = num + 1;
    std::vector<int> d;
    while (t > 0)
    {
        d.push_back(t % 10);
        t = t / 10;
    }
    int dn = d.size();
    int carry = 0;
    int ldi = dn; // largest discrepency index
    for (auto i = dn - 1; i > 0; --i)
    {
        if (d[i] >= d[i - 1])
        {
            if (9 == d[i]) carry = 1;
            ldi = i;
            break;
        }
    }
    if (dn == ldi) return num + 1;
    int sai = dn; // smallest ascension index
    for (auto i = ldi; i < dn; ++i)
    {
        if (i + d[i] + carry < 10)
        {
            sai = i;
            break;
        }
    }
    int rv = 0;
    if (dn == sai)
    {
        // have to make a longer number
        if (dn + 1 >= 10) return -1; // can't do it
        for (auto i = 1; i <= dn + 1; ++i)
        {
            rv *= 10; 
            rv += i;
        }
    }
    else
    {
        if (ldi != sai) carry = 1;
        // make ascending sequence from sai
        d[sai] += carry;
        for (auto i = sai - 1; i >= 0; --i)
        {
            d[i] = d[i + 1] + 1;
        }
        // get the new number
        for (auto i = dn - 1; i >= 0; --i)
        {
            rv *= 10;
            rv += d[i];
        }
    }
    return rv;
}

void test_next_larger_asc()
{
    assert(1234 == next_larger_asc(853));
    assert(5678 == next_larger_asc(5432));
    assert(1567 == next_larger_asc(1543));
    assert(1 == next_larger_asc(-3));
    assert(1678 == next_larger_asc(1589));
    assert(16789 == next_larger_asc(15831));
    assert(-1 == next_larger_asc(923456781));
}

- Omri.Bashari June 25, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is very efficient linear time solution.

They key insight to note is that all solutions is a substring of "123456789".
Given this insight, all you have to do is generate all substrings of size k, where k is the length of the input number string. Then return the first substring that is greater then the input string's numeric value.

static String ref = "123456789";
  static int max = 123456789;
  
  public static String nextSequence(String str){
    int num = Integer.parseInt(str);
    if(num > max) return "";
    
    int k = str.length();
    for(int i = 0; i <= ref.length() - k; i++){
      int candidate = Integer.parseInt(ref.substring(i,i+k));
      if(candidate > num){
        return ""+candidate;
      }
    }
    
    if(k+1 <= ref.length()) return ref.substring(0,k+1);
    
    return "";
  }

- hellohello October 30, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Here is my solution: Running java code can be found at ideone.com/cTExme

I have taken the liberty of assuming that the example given by the author is wrong and for input 987, the next large value should be 1234.

The basic idea is as follows:

Step1:
First normalize the input number for 9. That is, If the input number has 9 in it then the next larger number is always going to spill into the next significant digit position.
If input has 9 in it, next number larger than current input not having 9 in it can be found using input + amount remaining to reach next significant digit change.
for example
for 192 --> we ned 8 to reach 200.
for 1922 --> we need 88 to reach 2000 etc.
The formula for this is 192+(10-92%10) So depending upon position of 9, 10 changes to 100 or 1000 etc.

Step2:
Now we have the number which does not have 9. So to satisfy requirement 1,2 and 3, get the first digit of that number say that digit is 3 and depending upon the size of the number
(for 20 size is 2, for 1111 size is 4), add next digits (4,5,6 etc) to this number forming next larger positive digit without repetition, incrementing digits and smallest one greater than input.

Edge case:
In Step2, if the first digit happens to be say 8 and the size of the input is 3, then while forming new integer, the value will reach 10. like first digit 8, next digit 9 and 3rd digit 10.
So 8910 wont be a valid 3 digit number. In that case, we have to get the number larger than currently generated number which wont have digits spilling over to 10 when formed a new number.

public class functionReturningInteger {

	public static void main(String[] args) {
		int input = 987;
		
		System.out.println("Next Number for " + input + " is " + nextInteger(input));
	}
	
	private static int nextInteger(int input) {
		
		//Step1 normalize the number for 9
		input = normalizeFor9(input);
		
		//Step2: Now get the first digit of the updated number to form increasing sequence
		int firstDigit = getFirstDigitOfInput(input);
		int sizeOfInput = String.valueOf(input).length();
		
		/*
		 * It may happen that while forming next number of same size, digit may spill over to 10. So get the next larger number which wont spill over to 10.
		 * if the size of the input is going to spill over into 10. The only possible number in that case is the number 1 followed by the size of the input
		 * example if the input is 800, the closes number is going to be 1000
		 */
		if(firstDigit+sizeOfInput > 9) {
			//
			input = (int) Math.pow(10, String.valueOf(input).length());
			firstDigit = getFirstDigitOfInput(input);
			sizeOfInput = String.valueOf(input).length();
		}
		
		StringBuffer finalNumber = new StringBuffer();
		finalNumber.append(firstDigit);
		while(sizeOfInput >finalNumber.toString().length()) {
			finalNumber.append(++firstDigit);
		}
		
		return Integer.valueOf(finalNumber.toString());
	}
	
	//Get the first digit of the given input
	private static int getFirstDigitOfInput(int input) {
		int firstDigit = input / (int) Math.pow(10, String.valueOf(input).length() - 1);
		return firstDigit;
	}
	
	
	/*Start from the right most digit
	 * if number has 9 in it, then increment the input by the place value of 9.
	 * For example on 79, 9 is at position 0 so increment by 1
	 * in 192, 9 is at ten position (position 1), so increment by 192+(10-92%10)
	 * in 933, 9 is at hundred position (position 2), so increment by 933+(100-933%100)
	 * in 19147, 9 is at thousand position (position 3) so increment by 19147+(1000-19147%1000)
	 */
	private static int normalizeFor9(int input) {
		while(findPosition(input,9) != -1) {
			int position = findPosition(input, 9);
			if(position == 0) {
				input++;
			}else {
				input = input + ((int)(Math.pow(10,position)) - input%(int)Math.pow(10,position));
			}
		}
		return input;
	}
	
	//Return the position of 9 in the input. If 9 does not exists, return -1.
	private static int findPosition(int input, int digit) {
		int position = 0;
		while(input != 0) {
			if(input%10 == digit) {
				return position;
			}else {
				input = input/10;
				position++;
			}
		}
		return -1;
	}
}

- Saurabh March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

/*assuming i/p of 987 should not return 1023 as digits in
 * 1023 aren't in incremental sequence
 */

int
num_check(char *num_strP) {
  int *num_arr=(int*)malloc(strlen(num_strP)*sizeof(int));
  int i=0, _ret=1;
  for(i=0; i<strlen(num_strP); i++) {
    num_arr[i]=num_strP[i]-48;
//    printf("dbg: %d\t", num_arr[i]);
  }
  for(i=0; i<strlen(num_strP)-1; i++) {
    if(num_arr[i]>=num_arr[i+1])  _ret =0; 
  }

  free(num_arr);
  return _ret;
}

int
num_checker(int numP) {
  int i=numP;
  char num_str[12]={0};
  while(1) {
    sprintf(num_str, "%d", ++i);
    if(num_check(num_str)){
      break;
    }   
    memset(num_str, 0, 12);
  }
  return i;
}

- asdf March 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Here is an example with a unit test included. Basically, if the input is n, we check if (n+1) satisfies the three conditions.

If it does, we return it. If it does not we increment it again and check. We keep incrementing till the result meets all requirements.

And, I assume the OP's example is incorrect. 987's output should be 1234 according to the requirements.

#include <cstdio>

// returns truw if the digits are not in incremental order
bool checkIncremental(int input) {
  bool check = true;
  while (input) {
    // next line checks if the inputs least significant
    // digit is bigger than the second least significant
    // digit or not 
    check = input % 10 > (input/10) % 10;
    if (!check) return true;
   input /= 10; 
  }
  return false;
}

// returns true if there are repeating digits
bool checkRepeat(int input) {
  int copy = input; // make a copy of the input
  if (input < 10)
    return false;    // pigeonhole principle

  if (input > 10000000000)  // not necessary if working with 16-bit ints
    return true;   //pigeonhole principle again

  int lastDigit = copy % 10;
  copy /= 10;
  while (copy){
    if (copy % 10 == lastDigit)
      return true;
    else
      copy = copy / 10; 
  }
  return checkRepeat(input/10);
}


int nextInteger(int input) {
  if (input < 0)
    return 1;
  input++;
  while (checkRepeat(input) || checkIncremental(input) ) 
    input++;
  return input;
}


int main() {
  int i = 1;
  while (i) {
    scanf("%d", &i);
    printf("result %d\n", nextInteger(i));
  }
  return 0;
}

And my function accepts and returns an integer, as opposed to a string. But it is trivial to convert back and forth between them

- gokayhuz March 11, 2014 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More