Friday, November 29, 2013
No. 49 - Longest Substring without Duplication
Problem:
Given a string, please get the length of the longest substring which does not
have duplicated characters. Supposing all characters in the string are in the
range from ‘a’ to ‘z’.
Analysis:
It’s not difficult to get all substrings of a string, and to check whether a
substring has duplicated characters. The only concern about this brute-force
strategy is performance. A string with n
characters has O(n2)
substrings, and it costs O(n) time to
check whether a substring has duplication. Therefore, the overall cost is O(n3).
We may improve the efficiency with dynamic programming. Let’s
denote the length of longest substring ending with the ith character by L(i).
We scan the string one character after another. When the ith character is scanned, L(i-1)
is already know. If the ith
character has not appeared before, L(i) should be L(i-1)+1. It’s more
complex when the ith
character is duplicated. Firstly we get the distance between the ith character and its
previous occurrence. If the distance is greater than L(i-1), the character is
not in longest substring without duplication ending with the (i-1)th
character, so L(i) should also be L(i-1)+1. If the distance is less than L(i-1),
L(i)
is the distance, and it means between the two occurrence of the ith character there are no
other duplicated characters.
This solution can be implemented in Java as the following
code:
publicstaticint longestSubstringWithoutDuplication(String str) {
int curLength = 0;
int maxLength = 0;
int position[] = newint[26];
for(int i = 0; i < 26; ++i) {
position[i] = -1;
}
for(int i = 0; i < str.length(); ++i) {
int prevIndex = position[str.charAt(i) - 'a'];
if(prevIndex < 0 || i - prevIndex > curLength) {
++curLength;
}
else {
if(curLength > maxLength) {
maxLength = curLength;
}
curLength = i - prevIndex;
}
position[str.charAt(i) - 'a'] = i;
}
if(curLength > maxLength) {
maxLength = curLength;
}
return maxLength;
}
L(i) is implemented as curLength in the code above. An
integer array is used to store the positions of each character.
More coding interview questions are discussed in my book
<Coding Interviews: Questions, Analysis & Solutions>. You may find
the details of this book on Amazon.com , or Apress .
The
author Harry He owns all the rights of this post. If you are going to use part
of or the whole of this ariticle in your blog or webpages, please add a
reference to http://codercareer.blogspot.com/ .
If you are going to use it in your books, please contact him via
zhedahht@gmail.com . Thanks.
Thursday, November 28, 2013
No. 48 - Least Number after Deleting Digits
Problem: Please
get the least number after deleting k
digits from the input number. For example, if the input number is 24635, the
least number is 23 after deleting 3 digits.
Analysis: Let’s
delete a digit from the number at each step. What’s the first digit to be
deleted from the number 24635, in order to get the least number with the
remaining digits? We may list all the remaining numbers after deleting a digit,
in the following table:
Deleted
Digit
Remaining
Number
2
4635
4
2635
6
2435
3
2465
5
2463
The number 2435 is the least one in all remaining numbers, by deleting the digit 6. Notice that the digit 6 is the first digit in the number 24635 which is greater than the next digit.
Let’s delete another digit from the number 2435, the
remaining least number after the first step. We may summarize the remaining
numbers after delete every digit from it in the following table:
Deleted
Digit
Remaining
Number
2
435
4
235
3
245
5
243
The number 235 is the least one in all remaining numbers, by deleting the digit 4. Notice that the digit 4 is the first digit in the number 2435 which is greater than the next digit.
The remaining three digits in the number 235 are
increasingly sorted. What is the next digit to be deleted to get the least
remaining number? Again, we may list the remaining numbers after deleting each
digit in a table:
Deleted
Digit
Remaining
Number
2
35
3
25
5
23
The number 23 is the least one in all remaining numbers, by deleting the last digit 5.
If we are going to deleting more digits from a number whose
digits are increasingly sorted to get the least number, the last digit is
deleted at each step.
Now we get the rules to delete digits to get the least
remaining number: If there are digits who are greater than the next one,
delete the first digit. If all digits in the number are increasingly sorted,
delete the last digit gets deleted. The process repeats until the required k digits are deleted.
The code can be implemented in Java as the following:
publicstatic String getLeastNumberDeletingDigits_1(String number, int k) {
String leastNumber = number;
while(k > 0 && leastNumber.length() > 0) {
int firstDecreasingDigit = getFirstDecreasing(leastNumber);
if(firstDecreasingDigit >= 0) {
leastNumber =
removeDigit(leastNumber, firstDecreasingDigit);
}
else {
leastNumber =
removeDigit(leastNumber, leastNumber.length() - 1);
}
--k;
}
return leastNumber;
}
privatestaticint getFirstDecreasing(String number) {
for(int i = 0; i < number.length() - 1; ++i) {
int curDigit = number.charAt(i) - '0';
int nextDigit = number.charAt(i + 1) - '0';
if(curDigit > nextDigit) {
return i;
}
}
return -1;
}
privatestatic String removeDigit(String number, int digitIndex) {
String result = "";
if(digitIndex > 0) {
result = number.substring(0,
digitIndex);
}
if(digitIndex < number.length() - 1) {
result += number.substring(digitIndex +
1);
}
return result;
}
Optimization: Save the start index for the next round of search for
the first decreasing digit
In the method getFirstDecreasing
above to get the first digit which is greater than the next one, we always start
from the first digit. Is it necessary to start over in every round of search?
The answer is no. If the ith
digit is the first digit which is greater than the next one, all digits before
the ith digit are
increasingly sorted. The (i-1)th
digit might be less than the (i+1)th
digit, the next digit of the (i-1)th
digit after the ith digit
is deleted. Therefore, it is safe to start from the (i-1)th digit in the next round of search.
With this optimization strategy, the efficiency gets
improved from O(n*k) to O(n), if the length of the input number has n digits and k digits are
deleted.
The optimized solution can be implemented as:
classDecreasingResult {
publicint firstDecreasing;
publicint nextStart;
}
publicstatic String getLeastNumberDeletingDigits_2(String number, int k) {
String leastNumber = number;
int start = 0;
while(k > 0 && leastNumber.length() > 0) {
DecreasingResult result = getNextDecreasing(leastNumber, start);
if(result.firstDecreasing >= 0) {
leastNumber =
removeDigit(leastNumber, result.firstDecreasing);
}
else {
leastNumber = removeDigit(leastNumber,
leastNumber.length() - 1);
}
start = result.nextStart;
--k;
}
return leastNumber;
}
privatestatic DecreasingResult getNextDecreasing(String number, int start) {
int firstDecreasing = -1;
int nextStart;
for(int i = start; i < number.length() - 1; ++i) {
int curDigit = number.charAt(i) - '0';
int nextDigit = number.charAt(i + 1) - '0';
if(curDigit > nextDigit) {
firstDecreasing = i;
break;
}
}
if(firstDecreasing == 0) {
nextStart = 0;
}
elseif (firstDecreasing > 0) {
nextStart = firstDecreasing - 1;
}
else {
nextStart = number.length();
}
DecreasingResult result = new DecreasingResult();
result.firstDecreasing = firstDecreasing;
result.nextStart = nextStart;
return result;
}
More coding interview questions are discussed in my book <Coding Interviews: Questions, Analysis & Solutions>. You may find the details of this book on Amazon.com , or Apress .
The author Harry He owns all the rights of this post. If you are going to use part of or the whole of this ariticle in your blog or webpages, please add a reference to http://codercareer.blogspot.com/ . If you are going to use it in your books, please contact him via zhedahht@gmail.com . Thanks.
Labels:
Algorithm,
Amazon,
Google,
Interview Question,
String
Subscribe to:
Posts (Atom)