Thought:
Nothing easier than this....
Code:
public class Solution {
public int climbStairs(int n) {
int[] result = new int[n + 2];
result[1] = 1;
for(int i = 2; i < n + 2; i++) {
result[i] = result[i - 1] + result[i - 2];
}
return result[n + 1];
}
}
Thursday, February 28, 2013
[LeetCode] Binary Tree Maximum Path Sum
Thought:
Use a class variable to keep track of the maximum path ever seen( either across the root of not).
Use another method to calculate the maximum path ends with some specific node.
Then get the result.
public class Solution {
public static int maxAcrossRoot = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxAcrossRoot = Integer.MIN_VALUE;
int result = maxEndsRoot(root);
return Math.max(result, maxAcrossRoot);
}
public int maxEndsRoot(TreeNode root) {
if(root == null) return 0;
int left = maxEndsRoot(root.left);
int right = maxEndsRoot(root.right);
int temp = root.val;
if(left > 0) temp += left;
if(right > 0) temp += right;
maxAcrossRoot = Math.max(temp, maxAcrossRoot);
return Math.max(root.val, Math.max(root.val + left, root.val + right));
}
}
Use a class variable to keep track of the maximum path ever seen( either across the root of not).
Use another method to calculate the maximum path ends with some specific node.
Then get the result.
public class Solution {
public static int maxAcrossRoot = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxAcrossRoot = Integer.MIN_VALUE;
int result = maxEndsRoot(root);
return Math.max(result, maxAcrossRoot);
}
public int maxEndsRoot(TreeNode root) {
if(root == null) return 0;
int left = maxEndsRoot(root.left);
int right = maxEndsRoot(root.right);
int temp = root.val;
if(left > 0) temp += left;
if(right > 0) temp += right;
maxAcrossRoot = Math.max(temp, maxAcrossRoot);
return Math.max(root.val, Math.max(root.val + left, root.val + right));
}
}
Wednesday, February 27, 2013
[LeetCode] Binary Tree Zigzag Level Order Traversal
Thought:
Basically the same with level order traversal. And a flag should be used for determining the order of some specific level.
Code:
public class Solution {
public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
int depth = 0;
Queue<TreeNode> q1 = new LinkedList<TreeNode>();
Queue<Integer> q2 = new LinkedList<Integer>();
if(root == null) return result;
q1.offer(root);
q2.offer(depth + 1);
while(q1.peek() != null) {
TreeNode element = q1.poll();
depth = q2.poll();
if(result.size() < depth) {
result.add(new ArrayList<Integer>());
}
if(depth % 2 == 1) {
result.get(depth - 1).add(element.val);
}else{
result.get(depth - 1).add(0,element.val);
}
if(element.left != null) {
q1.offer(element.left);
q2.offer(depth+1);
}
if(element.right != null) {
q1.offer(element.right);
q2.offer(depth+1);
}
}
return result;
}
}
[LeetCode] Binary Tree Level Order Traversal II
Thought:
Basically the same with prior problem, the only change is dealing with the result.
Code:
public class Solution {
public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
int depth = 0;
Queue<TreeNode> q1 = new LinkedList<TreeNode>();
Queue<Integer> q2 = new LinkedList<Integer>();
if(root == null) return result;
q1.offer(root);
q2.offer(depth + 1);
while(q1.peek() != null){
TreeNode element = q1.poll();
depth = q2.poll();
if(result.size() < depth){
result.add(0, new ArrayList<Integer>());
}
result.get(0).add(element.val);
if(element.left != null){
q1.offer(element.left);
q2.offer(depth + 1);
}
if(element.right != null){
q1.offer(element.right);
q2.offer(depth + 1);
}
}
return result;
}
}
[LeetCode] Binary Tree Level Order Traversal
Thought:
We use two Queue, one stores the TreeNode, one stores their corresponding depth.
public class Solution {
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
int depth = 0;
Queue<TreeNode> q1 = new LinkedList<TreeNode>();
Queue<Integer> q2 = new LinkedList<Integer>();
if(root == null) return result;
q1.offer(root);
q2.offer(depth + 1);
while(q1.peek() != null){
TreeNode element = q1.poll();
depth = q2.poll();
if(result.size() < depth){
result.add(new ArrayList<Integer>());
}
result.get(depth - 1).add(element.val);
if(element.left != null){
q1.offer(element.left);
q2.offer(depth + 1);
}
if(element.right != null){
q1.offer(element.right);
q2.offer(depth + 1);
}
}
return result;
}
}
We use two Queue, one stores the TreeNode, one stores their corresponding depth.
public class Solution {
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
int depth = 0;
Queue<TreeNode> q1 = new LinkedList<TreeNode>();
Queue<Integer> q2 = new LinkedList<Integer>();
if(root == null) return result;
q1.offer(root);
q2.offer(depth + 1);
while(q1.peek() != null){
TreeNode element = q1.poll();
depth = q2.poll();
if(result.size() < depth){
result.add(new ArrayList<Integer>());
}
result.get(depth - 1).add(element.val);
if(element.left != null){
q1.offer(element.left);
q2.offer(depth + 1);
}
if(element.right != null){
q1.offer(element.right);
q2.offer(depth + 1);
}
}
return result;
}
}
[LeetCode] Binary Tree Inorder Traversal
Thought:
It is common place to use stack to simulate recursion.
Code:
public class Solution {
public ArrayList<Integer> inorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
while(root != null || !s.empty()){
while(root!=null){
s.push(root);
root=root.left;
}
if(!s.empty()){
root = s.pop();
result.add(root.val);
root = root.right;
}
}
return result;
}
}
It is common place to use stack to simulate recursion.
Code:
public class Solution {
public ArrayList<Integer> inorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
while(root != null || !s.empty()){
while(root!=null){
s.push(root);
root=root.left;
}
if(!s.empty()){
root = s.pop();
result.add(root.val);
root = root.right;
}
}
return result;
}
}
Tuesday, February 26, 2013
[LeetCode] Best Time to Buy and Sell Stock II
Thought:
We just bought on the first day, and every time we can earn some money we sell it.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
if(prices.length == 0) return profit;
int bought = prices[0];
for(int i = 1; i < prices.length; i++) {
if( prices[i] > bought){
profit += prices[i] - bought;
}
bought = prices[i];
}
return profit;
}
}
We just bought on the first day, and every time we can earn some money we sell it.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
if(prices.length == 0) return profit;
int bought = prices[0];
for(int i = 1; i < prices.length; i++) {
if( prices[i] > bought){
profit += prices[i] - bought;
}
bought = prices[i];
}
return profit;
}
}
[LeetCode] Best Time to Buy and Sell Stock III
Thought:
Divide the array into two parts, find two profits, and add them together.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
for(int i = 0; i < prices.length ; i++){
if( forwardProfit(prices,i) + backwardProfit(prices,i) > profit ){
profit = forwardProfit(prices,i) + backwardProfit(prices,i);
}
}
return profit;
}
public int forwardProfit(int[] prices, int n){
if(prices.length==0) return 0;
int min = prices[0] ;
int profit = 0;
for(int i = 0; i < n; i++){
if( prices[i] < min ){
min = prices[i];
}else if( prices[i] - min > profit ){
profit = prices[i] - min;
}
}
return profit;
}
public int backwardProfit(int[] prices, int n){
if(prices.length==0) return 0;
int max = prices[prices.length-1] ;
int profit = 0;
for(int i = prices.length - 1; i > n - 1; i--){
if( prices[i] > max ){
max = prices[i];
}else if( max - prices[i] > profit ){
profit = max - prices[i];
}
}
return profit;
}
}
Divide the array into two parts, find two profits, and add them together.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
for(int i = 0; i < prices.length ; i++){
if( forwardProfit(prices,i) + backwardProfit(prices,i) > profit ){
profit = forwardProfit(prices,i) + backwardProfit(prices,i);
}
}
return profit;
}
public int forwardProfit(int[] prices, int n){
if(prices.length==0) return 0;
int min = prices[0] ;
int profit = 0;
for(int i = 0; i < n; i++){
if( prices[i] < min ){
min = prices[i];
}else if( prices[i] - min > profit ){
profit = prices[i] - min;
}
}
return profit;
}
public int backwardProfit(int[] prices, int n){
if(prices.length==0) return 0;
int max = prices[prices.length-1] ;
int profit = 0;
for(int i = prices.length - 1; i > n - 1; i--){
if( prices[i] > max ){
max = prices[i];
}else if( max - prices[i] > profit ){
profit = max - prices[i];
}
}
return profit;
}
}
[LeetCode] Best Time to Buy and Sell Stock I
Thought:
Just Keep track of the min price and the local max profit.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
if(prices.length == 0) return profit;
int min = prices[0];
for(int i = 1; i < prices.length; i++) {
if( prices[i] - min > profit){
profit = prices[i] - min;
}else if( prices[i] < min) {
min = prices[i];
}
}
return profit;
}
}
Just Keep track of the min price and the local max profit.
Code:
public class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
if(prices.length == 0) return profit;
int min = prices[0];
for(int i = 1; i < prices.length; i++) {
if( prices[i] - min > profit){
profit = prices[i] - min;
}else if( prices[i] < min) {
min = prices[i];
}
}
return profit;
}
}
[LeetCode] Balanced Binary Tree
Thought:
To prevent redundant computation, we'd better first examine the flag of the left subtree and then the right one.
-1 means unbalanced and if not -1 it means the height.
Code:
public class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) {
return true;
}else{
return flag(root) == -1? false: true;
}
}
public int flag(TreeNode root) {
if(root == null) {
return 0;
}else{
int lFlag = flag(root.left);
if(lFlag == -1) return -1;
int rFlag = flag(root.right);
if(rFlag == -1) return -1;
return Math.abs(lFlag - rFlag) <= 1? Math.max(lFlag, rFlag) + 1: -1;
}
}
}
To prevent redundant computation, we'd better first examine the flag of the left subtree and then the right one.
-1 means unbalanced and if not -1 it means the height.
Code:
public class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) {
return true;
}else{
return flag(root) == -1? false: true;
}
}
public int flag(TreeNode root) {
if(root == null) {
return 0;
}else{
int lFlag = flag(root.left);
if(lFlag == -1) return -1;
int rFlag = flag(root.right);
if(rFlag == -1) return -1;
return Math.abs(lFlag - rFlag) <= 1? Math.max(lFlag, rFlag) + 1: -1;
}
}
}
[LeetCode] Anagrams
Thought:
Use a HashMap to store the sorted-original pairs, if there are several original string that relates to the same sorted string, they are anagrams!
Code:
import java.util.Iterator;
public class Solution {
public ArrayList<String> anagrams(String[] strs) {
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> result = new ArrayList<String>();
for (int i = 0; i < strs.length; i++) {
String key = sortWord(strs[i]);
if (!map.containsKey(key)) {
ArrayList<String> value = new ArrayList<String>();
value.add(strs[i]);
map.put(key, value);
}
else {
ArrayList<String> value = map.get(key);
value.add(strs[i]);
map.put(key, value);
}
}
Iterator<ArrayList<String>> it = map.values().iterator();
while (it.hasNext()) {
ArrayList<String> v = it.next();
if (v.size() >= 2) {
result.addAll(v);
}
}
return result;
}
public String sortWord(String word){
char[] charArr = word.toCharArray();
Arrays.sort(charArr);
return new String(charArr);
}
}
Use a HashMap to store the sorted-original pairs, if there are several original string that relates to the same sorted string, they are anagrams!
Code:
import java.util.Iterator;
public class Solution {
public ArrayList<String> anagrams(String[] strs) {
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> result = new ArrayList<String>();
for (int i = 0; i < strs.length; i++) {
String key = sortWord(strs[i]);
if (!map.containsKey(key)) {
ArrayList<String> value = new ArrayList<String>();
value.add(strs[i]);
map.put(key, value);
}
else {
ArrayList<String> value = map.get(key);
value.add(strs[i]);
map.put(key, value);
}
}
Iterator<ArrayList<String>> it = map.values().iterator();
while (it.hasNext()) {
ArrayList<String> v = it.next();
if (v.size() >= 2) {
result.addAll(v);
}
}
return result;
}
public String sortWord(String word){
char[] charArr = word.toCharArray();
Arrays.sort(charArr);
return new String(charArr);
}
}
[LeetCode] Add Binary
Thought:
It is easy.
Code:
public class Solution {
public String addBinary(String a, String b) {
StringBuilder result = new StringBuilder();
int m = a.length();
int n = b.length();
int len = Math.max(m, n);
int carry = 0;
for(int i = 0; i < len; i++) {
int x = getIndex(a, m - 1 - i);
int y = getIndex(b, n - 1 - i);
result.insert(0, (x + y + carry) % 2);
carry = (x + y + carry) / 2;
}
if(carry == 1) {
result.insert(0, 1);
}
return result.toString();
}
public int getIndex(String s, int index) {
if(index < 0 || index > s.length() - 1) {
return 0;
}else {
return s.charAt(index) == '0'? 0: 1;
}
}
}
Second Round Code:
public class Solution {
public String addBinary(String a, String b) {
StringBuilder ret = new StringBuilder();
int carry = 0;
int retLength = Math.max(a.length(), b.length());
int i = a.length() - 1;
int j = b.length() - 1;
while (retLength-- > 0) {
int temp = getInt(a, i--) + getInt(b, j--) + carry;
ret.append(temp % 2);
carry = temp / 2;
}
if (carry == 1) ret.append(1);
return ret.reverse().toString();
}
public int getInt (String s, int index) {
if (index < 0 || index > s.length() - 1) return 0;
return s.charAt(index) == '0'? 0 : 1 ;
}
}
It is easy.
Code:
public class Solution {
public String addBinary(String a, String b) {
StringBuilder result = new StringBuilder();
int m = a.length();
int n = b.length();
int len = Math.max(m, n);
int carry = 0;
for(int i = 0; i < len; i++) {
int x = getIndex(a, m - 1 - i);
int y = getIndex(b, n - 1 - i);
result.insert(0, (x + y + carry) % 2);
carry = (x + y + carry) / 2;
}
if(carry == 1) {
result.insert(0, 1);
}
return result.toString();
}
public int getIndex(String s, int index) {
if(index < 0 || index > s.length() - 1) {
return 0;
}else {
return s.charAt(index) == '0'? 0: 1;
}
}
}
Second Round Code:
public class Solution {
public String addBinary(String a, String b) {
StringBuilder ret = new StringBuilder();
int carry = 0;
int retLength = Math.max(a.length(), b.length());
int i = a.length() - 1;
int j = b.length() - 1;
while (retLength-- > 0) {
int temp = getInt(a, i--) + getInt(b, j--) + carry;
ret.append(temp % 2);
carry = temp / 2;
}
if (carry == 1) ret.append(1);
return ret.reverse().toString();
}
public int getInt (String s, int index) {
if (index < 0 || index > s.length() - 1) return 0;
return s.charAt(index) == '0'? 0 : 1 ;
}
}
Monday, February 25, 2013
[LeetCode] Remove Element
Thought:
Iterate from the end of the array, if we find a match we exchange the current value and the len-1 index value, and then update the len.
Code:
public class Solution {
public int removeElement(int[] A, int elem) {
int len = A.length;
for(int i = A.length - 1; i >= 0; i--){
if(A[i] == elem){
A[i] = A[len - 1];
len--;
}
}
return len;
}
}
[LeetCode] Remove Duplicates from Sorted Array
Thought:
It is very easy..
Just scan the array, if the current value = index value, let the length - 1.
If the current value != index value, copy it into index's next place, and update index.
Code:
public class Solution {
public int removeDuplicates(int[] A) {
int index = 0;
int len = A.length;
if(A.length <= 1) return len;
for(int i = 1; i < A.length; i++){
if(A[i] == A[index]){
len--;
}else{
A[++index] = A[i];
}
}
return len;
}
}
It is very easy..
Just scan the array, if the current value = index value, let the length - 1.
If the current value != index value, copy it into index's next place, and update index.
Code:
public class Solution {
public int removeDuplicates(int[] A) {
int index = 0;
int len = A.length;
if(A.length <= 1) return len;
for(int i = 1; i < A.length; i++){
if(A[i] == A[index]){
len--;
}else{
A[++index] = A[i];
}
}
return len;
}
}
[LeetCode] Generate Parentheses
Thought:
Use Recursion,
if right = left = n, we update the result.
if right = left < n, we add "(",
if right < left = n, we add ")",
if right < left < n, we could add "(" or ")".
Code:
public class Solution {
public ArrayList<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
char[] temp = new char[2 * n];
build(result, 0, 0, n, temp);
return result;
}
public void build(ArrayList<String> result, int left, int right, int n, char[] temp){
if(left == right && left == n){
result.add(new String(temp));
return;
}else{// some kind of DFS
if(left < n){
temp[left + right] = '(';
build(result, left + 1, right, n, temp);
}
if(left > right){
temp[left + right] = ')';
build(result, left, right + 1, n, temp);
}
}
}
}
Use Recursion,
if right = left = n, we update the result.
if right = left < n, we add "(",
if right < left = n, we add ")",
if right < left < n, we could add "(" or ")".
Code:
public class Solution {
public ArrayList<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
char[] temp = new char[2 * n];
build(result, 0, 0, n, temp);
return result;
}
public void build(ArrayList<String> result, int left, int right, int n, char[] temp){
if(left == right && left == n){
result.add(new String(temp));
return;
}else{// some kind of DFS
if(left < n){
temp[left + right] = '(';
build(result, left + 1, right, n, temp);
}
if(left > right){
temp[left + right] = ')';
build(result, left, right + 1, n, temp);
}
}
}
}
[LeetCode] Swap Nodes in Pairs
Thought:
Usually, we keep a sentinel before the head in Linked List problems.
Make sure that do not forget some links when linking nodes, which will make the whole list be divided into several parts.
Code:
public class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null) return head;
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode ppre = sentinel;
ListNode pre = head;
ListNode current = head.next;
while(current != null){
pre.next = current.next;
current.next = pre;
ppre.next = current;
ppre = current;
current = pre.next;
if(current != null){
current = current.next;
pre = pre.next;
ppre = ppre.next;
}
}
return sentinel.next;
}
}
Usually, we keep a sentinel before the head in Linked List problems.
Make sure that do not forget some links when linking nodes, which will make the whole list be divided into several parts.
Code:
public class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null) return head;
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode ppre = sentinel;
ListNode pre = head;
ListNode current = head.next;
while(current != null){
pre.next = current.next;
current.next = pre;
ppre.next = current;
ppre = current;
current = pre.next;
if(current != null){
current = current.next;
pre = pre.next;
ppre = ppre.next;
}
}
return sentinel.next;
}
}
[LeetCode] Valid Parentheses
Thought:
Trivial using stack.
Code:
public class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++ ){
char tmp = s.charAt(i);
if(tmp == '(' || tmp == '[' || tmp == '{' ){
stack.push(tmp);
}else{
if(stack.isEmpty()){
return false;
}else if (tmp == ')'){
if(stack.pop() != '('){
return false;
}
}else if (tmp == ']'){
if(stack.pop() != '['){
return false;
}
}else{
if(stack.pop() != '{'){
return false;
}
}
}
}
return stack.isEmpty()? true: false;
}
}
Trivial using stack.
Code:
public class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++ ){
char tmp = s.charAt(i);
if(tmp == '(' || tmp == '[' || tmp == '{' ){
stack.push(tmp);
}else{
if(stack.isEmpty()){
return false;
}else if (tmp == ')'){
if(stack.pop() != '('){
return false;
}
}else if (tmp == ']'){
if(stack.pop() != '['){
return false;
}
}else{
if(stack.pop() != '{'){
return false;
}
}
}
}
return stack.isEmpty()? true: false;
}
}
[LeetCode] Remove Nth Node From End of List
Thought:
Use two pointers, there distance is N. When the second pointer move to the end, the first pointer will point to the Node to be deleted.
To track the Node before the deleted node, initialize a previous pointer.
Code:
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode first = head;
ListNode second = head;
ListNode previous = head;
while(n > 1){
second = second.next;
n--;
}
while(second.next != null){
previous = first;
first = first.next;
second = second.next;
}
if(first != head){//deleting first
previous.next = first.next;
}else{//deleting head
head = head.next;
}
return head;
}
}
Use two pointers, there distance is N. When the second pointer move to the end, the first pointer will point to the Node to be deleted.
To track the Node before the deleted node, initialize a previous pointer.
Code:
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode first = head;
ListNode second = head;
ListNode previous = head;
while(n > 1){
second = second.next;
n--;
}
while(second.next != null){
previous = first;
first = first.next;
second = second.next;
}
if(first != head){//deleting first
previous.next = first.next;
}else{//deleting head
head = head.next;
}
return head;
}
}
[LeetCode] Letter Combinations of a Phone Number
Thought:
It is an easy DP problem, we use the previous result to obtain the current result.
Code:
public class Solution {
public ArrayList<String> letterCombinations(String digits) {
ArrayList<String> result = new ArrayList<String>();
if(digits.length() == 0){
result.add("");
}else{
ArrayList<String> previous = letterCombinations(digits.substring(1));
char c = digits.charAt(0);
for(String i: previous){
if(c=='2'){
result.add("a" + i);result.add("b" + i);result.add("c" + i);
}else if(c=='3'){
result.add("d" + i);result.add("e" + i);result.add("f" + i);
}else if(c=='4'){
result.add("g" + i);result.add("h" + i);result.add("i" + i);
}else if(c=='5'){
result.add("j" + i);result.add("k" + i);result.add("l" + i);
}else if(c=='6'){
result.add("m" + i);result.add("n" + i);result.add("o" + i);
}else if(c=='7'){
result.add("p" + i);result.add("q" + i);
result.add("r" + i);result.add("s" + i);
}else if(c=='8'){
result.add("t" + i);result.add("u" + i);result.add("v" + i);
}else if(c=='9'){
result.add("w" + i);result.add("x" + i);
result.add("y" + i);result.add("z" + i);
}
}
}
return result;
}
}
It is an easy DP problem, we use the previous result to obtain the current result.
Code:
public class Solution {
public ArrayList<String> letterCombinations(String digits) {
ArrayList<String> result = new ArrayList<String>();
if(digits.length() == 0){
result.add("");
}else{
ArrayList<String> previous = letterCombinations(digits.substring(1));
char c = digits.charAt(0);
for(String i: previous){
if(c=='2'){
result.add("a" + i);result.add("b" + i);result.add("c" + i);
}else if(c=='3'){
result.add("d" + i);result.add("e" + i);result.add("f" + i);
}else if(c=='4'){
result.add("g" + i);result.add("h" + i);result.add("i" + i);
}else if(c=='5'){
result.add("j" + i);result.add("k" + i);result.add("l" + i);
}else if(c=='6'){
result.add("m" + i);result.add("n" + i);result.add("o" + i);
}else if(c=='7'){
result.add("p" + i);result.add("q" + i);
result.add("r" + i);result.add("s" + i);
}else if(c=='8'){
result.add("t" + i);result.add("u" + i);result.add("v" + i);
}else if(c=='9'){
result.add("w" + i);result.add("x" + i);
result.add("y" + i);result.add("z" + i);
}
}
}
return result;
}
}
[LeetCode] 4Sum
Thought:
Just like 3Sum, we can write an O(n^3) solution.
Code:
public class Solution {
public ArrayList<ArrayList> fourSum(int[] num, int target) {
Arrays.sort(num);
HashSet<ArrayList> result = new HashSet<ArrayList>();
for (int i = 0; i < num.length; i++) {
for (int j = i + 1; j < num.length; j++) {
for (int k = j + 1, l = num.length - 1; k < l;) {
int sum = num[i] + num[j] + num[k] + num[l];
if (sum > target) {
l--;
}
else if (sum < target) {
k++;
}else{
ArrayList tmp = new ArrayList();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[k]);
tmp.add(num[l]);
result.add(tmp);
k++;
l--;
}
}
}
}
return new ArrayList<ArrayList>(result);
}
}
Code second Round:
public class Solution {
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for (int i = 0; i < num.length - 1; i++) {
for (int j = i + 1; j < num.length; j++) {
int m = j + 1, n = num.length - 1;
while (m < n) {
if (num[i] + num[j] + num[m] + num[n] < target) m++;
else if (num[i] + num[j] + num[m] + num[n] > target) n--;
else {
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(num[i]);
temp.add(num[j]);
temp.add(num[m]);
temp.add(num[n]);
result.add(temp);
m++;
n--;
}
}
}
}
return new ArrayList<ArrayList<Integer>>(result);
}
}
Just like 3Sum, we can write an O(n^3) solution.
Code:
public class Solution {
public ArrayList<ArrayList> fourSum(int[] num, int target) {
Arrays.sort(num);
HashSet<ArrayList> result = new HashSet<ArrayList>();
for (int i = 0; i < num.length; i++) {
for (int j = i + 1; j < num.length; j++) {
for (int k = j + 1, l = num.length - 1; k < l;) {
int sum = num[i] + num[j] + num[k] + num[l];
if (sum > target) {
l--;
}
else if (sum < target) {
k++;
}else{
ArrayList tmp = new ArrayList();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[k]);
tmp.add(num[l]);
result.add(tmp);
k++;
l--;
}
}
}
}
return new ArrayList<ArrayList>(result);
}
}
Code second Round:
public class Solution {
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for (int i = 0; i < num.length - 1; i++) {
for (int j = i + 1; j < num.length; j++) {
int m = j + 1, n = num.length - 1;
while (m < n) {
if (num[i] + num[j] + num[m] + num[n] < target) m++;
else if (num[i] + num[j] + num[m] + num[n] > target) n--;
else {
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(num[i]);
temp.add(num[j]);
temp.add(num[m]);
temp.add(num[n]);
result.add(temp);
m++;
n--;
}
}
}
}
return new ArrayList<ArrayList<Integer>>(result);
}
}
[LeetCode] 3Sum Closest
Thought:
The basic pattern is just like the 3Sum.
Use a flag to store the difference between sum and the target, when we encounter a smaller difference ,we should update the difference and also update the result at the same time.
It is a O(n^2) solution.
Code:
public class Solution {
public int threeSumClosest(int[] num, int target) {
int dif = Integer.MAX_VALUE;
int result = target;
Arrays.sort(num);
for(int i = 0;i < num.length; i++){
int j = i + 1;
int k = num.length - 1;
while(j < k){
int sum = num[j] + num[k] + num[i];
if(sum == target){
return target;
}else if(sum > target){
k--;
}else{
j++;
}
if(dif > Math.abs(sum-target)){
result = sum;
}
dif = Math.min(dif, Math.abs(sum-target));
}
}
return result;
}
}
Second Round Code:
public class Solution {
public int threeSumClosest(int[] num, int target) {
int dif = Integer.MAX_VALUE;
int result = target;
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
int j = i + 1;
int k = num.length - 1;
while (j < k) {
int temp = num[i] + num[j] + num[k];
if (temp == target) return target;
if (temp < target) j++;
else k--;
if (dif > Math.abs(temp - target)) {
dif = Math.abs(temp - target);
result = temp;
}
}
}
return result;
}
}
The basic pattern is just like the 3Sum.
Use a flag to store the difference between sum and the target, when we encounter a smaller difference ,we should update the difference and also update the result at the same time.
It is a O(n^2) solution.
Code:
public class Solution {
public int threeSumClosest(int[] num, int target) {
int dif = Integer.MAX_VALUE;
int result = target;
Arrays.sort(num);
for(int i = 0;i < num.length; i++){
int j = i + 1;
int k = num.length - 1;
while(j < k){
int sum = num[j] + num[k] + num[i];
if(sum == target){
return target;
}else if(sum > target){
k--;
}else{
j++;
}
if(dif > Math.abs(sum-target)){
result = sum;
}
dif = Math.min(dif, Math.abs(sum-target));
}
}
return result;
}
}
Second Round Code:
public class Solution {
public int threeSumClosest(int[] num, int target) {
int dif = Integer.MAX_VALUE;
int result = target;
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
int j = i + 1;
int k = num.length - 1;
while (j < k) {
int temp = num[i] + num[j] + num[k];
if (temp == target) return target;
if (temp < target) j++;
else k--;
if (dif > Math.abs(temp - target)) {
dif = Math.abs(temp - target);
result = temp;
}
}
}
return result;
}
}
[LeetCode] 3Sum
Thought:
Sort and iterate the array, for every element, we find the other two elements whose sum is -num[i], it is a O(n^2) solution.
Code:
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
HashSet<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for(int i = 0;i < num.length; i++){
int j = i + 1;
int k = num.length - 1;
while(j < k){
if(num[j] + num[k] + num[i] < 0){
j++;
}else if(num[j] + num[k] + num[i] > 0){
k--;
}else{
ArrayList<Integer> tmp = new ArrayList<Integer>();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[k]);
result.add(tmp);
j++;
k--;
}
}
}
return new ArrayList<ArrayList<Integer>>(result);
}
}
Code when I met this problem the second time:
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
twoSum(Arrays.copyOfRange(num, i + 1, num.length), -num[i], result);
}
return new ArrayList<ArrayList<Integer>>(result);
}
public void twoSum(int[] array, int sum, Set<ArrayList<Integer>> result) {
if (array.length < 2) return;
int i = 0, j = array.length - 1;
while (i < j) {
if (array[i] + array[j] < sum) i++;
else if (array[i] + array[j] > sum) j--;
else {
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(-sum);
temp.add(array[i]);
temp.add(array[j]);
result.add(temp);
i++; // I forgot this two lines at first...............
j--;
}
}
}
}
Sort and iterate the array, for every element, we find the other two elements whose sum is -num[i], it is a O(n^2) solution.
Code:
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
HashSet<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for(int i = 0;i < num.length; i++){
int j = i + 1;
int k = num.length - 1;
while(j < k){
if(num[j] + num[k] + num[i] < 0){
j++;
}else if(num[j] + num[k] + num[i] > 0){
k--;
}else{
ArrayList<Integer> tmp = new ArrayList<Integer>();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[k]);
result.add(tmp);
j++;
k--;
}
}
}
return new ArrayList<ArrayList<Integer>>(result);
}
}
Code when I met this problem the second time:
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>();
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
twoSum(Arrays.copyOfRange(num, i + 1, num.length), -num[i], result);
}
return new ArrayList<ArrayList<Integer>>(result);
}
public void twoSum(int[] array, int sum, Set<ArrayList<Integer>> result) {
if (array.length < 2) return;
int i = 0, j = array.length - 1;
while (i < j) {
if (array[i] + array[j] < sum) i++;
else if (array[i] + array[j] > sum) j--;
else {
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(-sum);
temp.add(array[i]);
temp.add(array[j]);
result.add(temp);
i++; // I forgot this two lines at first...............
j--;
}
}
}
}
Sunday, February 24, 2013
[LeetCode] Longest Common Prefix
Thought:
For every string in the array, test their first character, and then second and then... until we found mismatch.
Code:
public class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length==0) return "";
int len = 0;
boolean flag = true;
while(flag){
for(int i = 0; i < strs.length; i++){
if( len >= strs[i].length() ){
flag = false;
break;
}else if( strs[i].charAt(len) != strs[0].charAt(len) ){
flag = false;
break;
}
}
if(flag) len++;
}
return strs[0].substring(0,len);
}
}
[LeetCode] Roman To Integer
Thought:
From the LSB to the MSB, if current bit's value is smaller than previous bit's value, we should minus this bit, otherwise add this bit.
Code:
public class Solution {
public int romanToInt(String s) {
HashMap<Character, Integer> roman = new HashMap<Character, Integer>();
roman.put('I', 1);
roman.put('V', 5);
roman.put('X', 10);
roman.put('L', 50);
roman.put('C', 100);
roman.put('D', 500);
roman.put('M', 1000);
int i = s.length() - 1;
int result = roman.get(s.charAt(i));
char current = ' ', previous = ' ';
while(i > 0){
previous = s.charAt(i);
current = s.charAt(i - 1);
if(roman.get(current) < roman.get(previous)){
result = result - roman.get(current);
}else{
result = result + roman.get(current);
}
i--;
}
return result;
}
}
[LeetCode] Integer To Roman
Thought:
Using a HashMap to store the relation between integer and Roman numerical.
It is really tricky that putting 4,9,40,90,400,900 into this map will result in an easier solution.
Code:
public class Solution {
public String intToRoman(int num) {
HashMap<Integer, String> roman = new HashMap<Integer, String>();
int[] base = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
roman.put(1, "I");
roman.put(4, "IV");
roman.put(5, "V");
roman.put(9, "IX");
roman.put(10, "X");
roman.put(40, "XL");
roman.put(50, "L");
roman.put(90, "XC");
roman.put(100, "C");
roman.put(400, "CD");
roman.put(500, "D");
roman.put(900, "CM");
roman.put(1000, "M");
String result = new String();
for( int temp : base ){
while( num >= temp ){
result = result + roman.get(temp);
num = num - temp;
}
}
return result;
}
}
2nd Round:
public class Solution {
public String intToRoman(int num) {
Map<Integer, String> dict = new HashMap<Integer, String>();
dict.put(1, "I");
dict.put(4, "IV");
dict.put(5, "V");
dict.put(9, "IX");
dict.put(10, "X");
dict.put(40, "XL");
dict.put(50, "L");
dict.put(90, "XC");
dict.put(100, "C");
dict.put(400, "CD");
dict.put(500, "D");
dict.put(900, "CM");
dict.put(1000, "M");
int[] key = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
StringBuilder sb = new StringBuilder();
int index = key.length - 1;
while (num > 0) {
while (num >= key[index]) {
sb.append(dict.get(key[index]));
num -= key[index];
}
index--;
}
return sb.toString();
}
}
Using a HashMap to store the relation between integer and Roman numerical.
It is really tricky that putting 4,9,40,90,400,900 into this map will result in an easier solution.
Code:
public class Solution {
public String intToRoman(int num) {
HashMap<Integer, String> roman = new HashMap<Integer, String>();
int[] base = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
roman.put(1, "I");
roman.put(4, "IV");
roman.put(5, "V");
roman.put(9, "IX");
roman.put(10, "X");
roman.put(40, "XL");
roman.put(50, "L");
roman.put(90, "XC");
roman.put(100, "C");
roman.put(400, "CD");
roman.put(500, "D");
roman.put(900, "CM");
roman.put(1000, "M");
String result = new String();
for( int temp : base ){
while( num >= temp ){
result = result + roman.get(temp);
num = num - temp;
}
}
return result;
}
}
2nd Round:
public class Solution {
public String intToRoman(int num) {
Map<Integer, String> dict = new HashMap<Integer, String>();
dict.put(1, "I");
dict.put(4, "IV");
dict.put(5, "V");
dict.put(9, "IX");
dict.put(10, "X");
dict.put(40, "XL");
dict.put(50, "L");
dict.put(90, "XC");
dict.put(100, "C");
dict.put(400, "CD");
dict.put(500, "D");
dict.put(900, "CM");
dict.put(1000, "M");
int[] key = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
StringBuilder sb = new StringBuilder();
int index = key.length - 1;
while (num > 0) {
while (num >= key[index]) {
sb.append(dict.get(key[index]));
num -= key[index];
}
index--;
}
return sb.toString();
}
}
[LeetCode] Container with Most Water
Thought:
Calculate from both side leads to a O(n) solution.
Code:
public class Solution {
public int maxArea(int[] height) {
int i = 0;
int j = height.length - 1;
int result = 0;
while( i < j ){
result = Math.max( Math.min(height[i], height[j]) * (j - i), result);
if(height[i] < height[j]){
i++;
}else{
j--;
}
}
return result;
}
}
Calculate from both side leads to a O(n) solution.
Code:
public class Solution {
public int maxArea(int[] height) {
int i = 0;
int j = height.length - 1;
int result = 0;
while( i < j ){
result = Math.max( Math.min(height[i], height[j]) * (j - i), result);
if(height[i] < height[j]){
i++;
}else{
j--;
}
}
return result;
}
}
[LeetCode] Regular Expression Matching
Thought:
It is a 2-dimentional Dynamic Programming.
Code:
public class Solution {
public boolean isMatch(String s, String p) {
int m = s.length() + 1;
int n = p.length() + 1;
boolean[][] result = new boolean[n][m];
result[0][0] = true;
for( int i = 1; i < n; i++){
result[i][0] = p.charAt(i-1) == '*' ? result[i-2][0] : false;
}
for( int j = 1; j < m; j++){
result[0][j] = s.charAt(j-1) == '*' ? result[0][j-2] : false;
}
for( int i = 1; i < n; i++ ){
for( int j = 1; j < m; j++ ){
if(p.charAt(i-1) == '*')
result[i][j] = match(s.charAt(j-1),p.charAt(i-2)) ? (result[i][j-1]||result[i-2][j]) : result[i-2][j];
else
result[i][j] = match(s.charAt(j-1),p.charAt(i-1)) ? result[i-1][j-1] : false;
}
}
return result[n-1][m-1];
}
boolean match(char a, char b){
if(a == '.' || b == '.')
return true;
else
return a == b;
}
}
It is a 2-dimentional Dynamic Programming.
Code:
public class Solution {
public boolean isMatch(String s, String p) {
int m = s.length() + 1;
int n = p.length() + 1;
boolean[][] result = new boolean[n][m];
result[0][0] = true;
for( int i = 1; i < n; i++){
result[i][0] = p.charAt(i-1) == '*' ? result[i-2][0] : false;
}
for( int j = 1; j < m; j++){
result[0][j] = s.charAt(j-1) == '*' ? result[0][j-2] : false;
}
for( int i = 1; i < n; i++ ){
for( int j = 1; j < m; j++ ){
if(p.charAt(i-1) == '*')
result[i][j] = match(s.charAt(j-1),p.charAt(i-2)) ? (result[i][j-1]||result[i-2][j]) : result[i-2][j];
else
result[i][j] = match(s.charAt(j-1),p.charAt(i-1)) ? result[i-1][j-1] : false;
}
}
return result[n-1][m-1];
}
boolean match(char a, char b){
if(a == '.' || b == '.')
return true;
else
return a == b;
}
}
[LeetCode] Palindrome Number
Thought:
Pick a base number which is the biggest 10^n smaller than x ->
Compare the Most Significant Bit and the Least Significant Bit ->
Remove the MSB and the LSB from x ->
Update the base number ->
Result
Code:
public class Solution {
public boolean isPalindrome(int x) {
if( x < 0 ) return false;
int base = 1;
int temp = x;
while( temp/10 != 0 ){
base = base * 10;
temp = temp / 10;
}
while( base > 1 ){
int MSB = x / base;
int LSB = x % 10;
if( MSB != LSB ) return false;
x = x % base;
x = x / 10;
base = base / 100;
}
return true;
}
}
Pick a base number which is the biggest 10^n smaller than x ->
Compare the Most Significant Bit and the Least Significant Bit ->
Remove the MSB and the LSB from x ->
Update the base number ->
Result
Code:
public class Solution {
public boolean isPalindrome(int x) {
if( x < 0 ) return false;
int base = 1;
int temp = x;
while( temp/10 != 0 ){
base = base * 10;
temp = temp / 10;
}
while( base > 1 ){
int MSB = x / base;
int LSB = x % 10;
if( MSB != LSB ) return false;
x = x % base;
x = x / 10;
base = base / 100;
}
return true;
}
}
[LeetCode] String to Integer
Thought:
Skip whitespace -> Check Sign -> Check Digit -> Check Overflow -> Result
When dealing with overflow, we could write neither
result * 10 > Integer.MAX_VALUE - temp nor
result * 10 + temp > Integer.MAX_VALUE
Because both of their left side might overflows which will lead to the wrong answer.
Code:
public class Solution {
public int atoi(String str) {
int i = 0, result = 0, sign = 1;
char c = ' ';
while (i < str.length()) {
c = str.charAt(i);
if (Character.isWhitespace(c)) {
i++;
}else if (c == '+' || c == '-' ) {
i++;
if( c == '-' ) sign = -1;
break;
}else if(Character.isDigit(c)){
break;
}else{
return 0;
}
}
while (i < str.length()) {
c = str.charAt(i);
if (!Character.isDigit(c)){
break;
}else{
int temp = Character.digit(c, 10);
if( result > (Integer.MAX_VALUE - temp)/10 ){
return sign < 0? Integer.MIN_VALUE: Integer.MAX_VALUE;
}else{
result = result * 10 + temp;
}
}
i++;
}
return sign * result;
}
}
Skip whitespace -> Check Sign -> Check Digit -> Check Overflow -> Result
When dealing with overflow, we could write neither
result * 10 > Integer.MAX_VALUE - temp nor
result * 10 + temp > Integer.MAX_VALUE
Because both of their left side might overflows which will lead to the wrong answer.
Code:
public class Solution {
public int atoi(String str) {
int i = 0, result = 0, sign = 1;
char c = ' ';
while (i < str.length()) {
c = str.charAt(i);
if (Character.isWhitespace(c)) {
i++;
}else if (c == '+' || c == '-' ) {
i++;
if( c == '-' ) sign = -1;
break;
}else if(Character.isDigit(c)){
break;
}else{
return 0;
}
}
while (i < str.length()) {
c = str.charAt(i);
if (!Character.isDigit(c)){
break;
}else{
int temp = Character.digit(c, 10);
if( result > (Integer.MAX_VALUE - temp)/10 ){
return sign < 0? Integer.MIN_VALUE: Integer.MAX_VALUE;
}else{
result = result * 10 + temp;
}
}
i++;
}
return sign * result;
}
}
[LeetCode] Reverse Integer
Thought:
If a positive number reverse to a negative one, it means overflow in my opinion.
Zero is a special number that none of the integer's reverse is zero, so I chose it as the flag of overflow.
Code:
public class Solution {
public int reverse(int x) {
boolean isNegative = false;
if( x < 0) {
isNegative = true;
x = -x;
}
int result = 0;
while( x / 10 != 0 ){
int LSB = x % 10;
x = x / 10;
result = result * 10 + LSB;
}
result = result * 10 + x;
if( result < 0 ){//overflow
return 0;
}
if( isNegative ){
return -result;
}else{
return result;
}
}
}
If a positive number reverse to a negative one, it means overflow in my opinion.
Zero is a special number that none of the integer's reverse is zero, so I chose it as the flag of overflow.
Code:
public class Solution {
public int reverse(int x) {
boolean isNegative = false;
if( x < 0) {
isNegative = true;
x = -x;
}
int result = 0;
while( x / 10 != 0 ){
int LSB = x % 10;
x = x / 10;
result = result * 10 + LSB;
}
result = result * 10 + x;
if( result < 0 ){//overflow
return 0;
}
if( isNegative ){
return -result;
}else{
return result;
}
}
}
[LeetCode] ZigZag Conversion
Thought:
For the first and last row, we add one character per cycle, the cycle distance is 2*nRows -2.
While for the other rows, we add two character per cycle, the distance between two added characters is 2*nRows -2 - 2*i.
Code:
public class Solution {
public String convert(String s, int nRows) {
String result = "";
int index = 0;
if( s.length() == 0 || nRows == 1 ){
return s;
}
for( int i = 0; i < nRows; i++ ){
if( i == 0 || i == nRows - 1 ){// add one elements per cycle
for( int j = 0; ; j++ ){
index = i + j * ( 2 * nRows - 2 );
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
}
}else{// add two elements per cycle
for( int j = 0; ; j++ ){
index = i + j * ( 2 * nRows - 2);
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
index = index + 2 * nRows - 2 * i -2;
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
}
}
}
return result;
}
}
For the first and last row, we add one character per cycle, the cycle distance is 2*nRows -2.
While for the other rows, we add two character per cycle, the distance between two added characters is 2*nRows -2 - 2*i.
Code:
public class Solution {
public String convert(String s, int nRows) {
String result = "";
int index = 0;
if( s.length() == 0 || nRows == 1 ){
return s;
}
for( int i = 0; i < nRows; i++ ){
if( i == 0 || i == nRows - 1 ){// add one elements per cycle
for( int j = 0; ; j++ ){
index = i + j * ( 2 * nRows - 2 );
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
}
}else{// add two elements per cycle
for( int j = 0; ; j++ ){
index = i + j * ( 2 * nRows - 2);
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
index = index + 2 * nRows - 2 * i -2;
if( index >= s.length() ){
break;
}
result = result.concat( s.substring( index, index + 1 ) );
}
}
}
return result;
}
}
Wednesday, February 20, 2013
[LeetCode] Longest PalinDromic Substring
Thought:
It is not difficult to come up with the idea to populate every character and expand along its two sides. This method will get a O(n^2) time complexity.
There surprisingly exists a very nontrivial algorithm here whose time complexity is O(n)! Manacher’s Algorithm
Code:
public class Solution {
public String longestPalindrome(String s) {
String input = preProcess(s);
int len = input.length();
int[] P = new int[len];
int center = 0, right = 0;
for( int i = 1; i < len - 1; i++ ){
int j = 2 * center - i;
P[i] = right > i? Math.min( right - i, P[j] ): 0;
while( input.charAt(i + P[i] + 1) == input.charAt(i - P[i] - 1) ){
P[i]++;
}
if( i + P[i] > right){
right = i + P[i];
center = i;
}
}
int resultc = 0, resultl = 0;
for( int i = 0 ; i < len; i++ ){
if(P[i]>resultl){
resultc = i;
resultl = P[i];
}
}
return s.substring( (resultc - resultl - 1)/2, (resultc + resultl)/2 - 0 );
}
public String preProcess(String s){
String temp = "!#";
for( int i = 0; i < s.length(); i++ ){
temp = temp + s.substring(i, i + 1);
temp = temp + "#";
}
temp = temp + "@";
return temp;
}
}
Monday, February 18, 2013
[Cracking The Code Interview] 1-1
Description:
Implement an algorithm to determine if a string has all unique characters. What if you cannot use additional data structures?
Thoughts:
If we could use arrays, it is trivial to implement. Without additional data structures, we could pick up a int variable and use bit manipulation to trace whether a character has shown up in the string before.
Code:
public static boolean IsUniqueChar(String s){ //Use an extra array
boolean[] char_set = new boolean[256];
for(int i = 0; i < s.length(); i++){
int tmp = s.charAt(i);
if(char_set[tmp]){
return false;
}
char_set[tmp] = true;
}
return true;
}
public static boolean IsUniqueChar2(String s){ // Use bit manipulation
int flag = 0;
for(int i = 0; i <s.length(); i++){
int tmp = s.charAt(i) - 'a';
if( (flag & (1<<tmp)) > 0 ){
return false;
}
flag = flag | (1<<tmp) ;
}
return true;
}
Saturday, February 16, 2013
[LeetCode] Add Two Numbers
Thoughts:
Use a easy tail recursion taking the carry bit into consideration.
Code:
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return add(l1, l2, 0);
}
public ListNode add(ListNode l1, ListNode l2, int carry){
ListNode result = null;
int temp = 0;
if( l1 != null && l2 != null){
int val = l1.val + l2.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(l1.next, l2.next, temp);
}else if( l1 == null && l2 != null){
int val = l2.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(null, l2.next, temp);
}else if( l1 != null && l2 == null){
int val = l1.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(l1.next, null, temp);
}else{
if( carry == 1 ){
result = new ListNode(carry);
}
}
return result;
}
}
Use a easy tail recursion taking the carry bit into consideration.
Code:
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return add(l1, l2, 0);
}
public ListNode add(ListNode l1, ListNode l2, int carry){
ListNode result = null;
int temp = 0;
if( l1 != null && l2 != null){
int val = l1.val + l2.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(l1.next, l2.next, temp);
}else if( l1 == null && l2 != null){
int val = l2.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(null, l2.next, temp);
}else if( l1 != null && l2 == null){
int val = l1.val + carry;
result = new ListNode(val%10);
temp = val > 9? 1: 0;
result.next = add(l1.next, null, temp);
}else{
if( carry == 1 ){
result = new ListNode(carry);
}
}
return result;
}
}
[LeetCode] Longest Substring Without Repeating Characters
Thought:
Try to implement a O(n) method using just one scan of the String.
Use a HashMap to track which letter has occured.
Code:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
int length = 0;
HashMap<Character, Integer> index = new HashMap<Character, Integer>();
for( int i = 0; i < s.length(); i++ ){
char temp = s.charAt(i);
if( !index.containsKey(temp) ){
index.put(temp,i);
length++;
max = Math.max(length, max);
}else{
i = index.get(temp);
index.clear();
length = 0;
}
}
return max;
}
}
Try to implement a O(n) method using just one scan of the String.
Use a HashMap to track which letter has occured.
Code:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
int length = 0;
HashMap<Character, Integer> index = new HashMap<Character, Integer>();
for( int i = 0; i < s.length(); i++ ){
char temp = s.charAt(i);
if( !index.containsKey(temp) ){
index.put(temp,i);
length++;
max = Math.max(length, max);
}else{
i = index.get(temp);
index.clear();
length = 0;
}
}
return max;
}
}
Friday, February 15, 2013
[LeetCode] Median of Two Sorted Arrays
Thought:
The O(m+n) solution is trivial. However, we could improve it to O(lg(m+n)) by using kind of divide and conquer method.
The key is to note that: when we remove the same amount of values from the start and end of a sorted array, its median remains the same.
We could directly compare the median of array A and array B( respectively A[i] and B[j]) in O(1) time, and then remove some values before A[i] and after B[j](or before B[j] and after A[i]---- it depends on the size of A and B actually). By this way, we quickly decrease the problem size.
While the most difficult part of this problem is to consider the base case and code them out. Believe in yourself and code them out!
Code(all the max and min method could be expanded to be easier to understand):
public class Solution {
public double findMedianSortedArrays(int A[], int B[]) {
double result = 0;
int m = A.length;
int n = B.length;
if( m == 0 ){
result = B[n/2] + B[(n-1)/2];
result = result/2;
}else if( n == 0 ){
result = findMedianSortedArrays(B, A);
}else if( m == 1 ){
if( n%2 == 0 ){
result = Math.min( B[n/2], Math.max(A[0], B[n/2-1]) );
}else{
if( n == 1 ){
result = A[0] + B[0];
}else{
result = B[n/2] + Math.min( B[n/2+1], Math.max(A[0], B[n/2-1]) );
}
result = result/2;
}
}else if( n == 1 ){
result = findMedianSortedArrays(B, A);
}else if( m == 2){
if( n == 2 ){
result = Math.max(A[0],B[n/2-1]) + Math.min(A[1],B[n/2]);
result = result/2;
}else if( n%2 == 0 ){
result = Math.max(B[n/2-2], Math.min(A[1], B[n/2])) + Math.min(B[n/2+1], Math.max(A[0],B[n/2-1]));
result = result/2;
}else{
result = Math.max(B[n/2-1], Math.min(B[n/2+1], Math.max(A[0], Math.min(B[n/2], A[1]))));
}
}else if( n == 2){
result = findMedianSortedArrays(B, A);
}else{
int temp = (Math.min(m, n)-1)/2;
if(A[m/2] < B[n/2]){
A = Arrays.copyOfRange(A, temp, m);
B = Arrays.copyOfRange(B, 0, n-temp);
}else{
A = Arrays.copyOfRange(A, 0, m-temp);
B = Arrays.copyOfRange(B, temp, n);
}
result = findMedianSortedArrays(A, B);
}
return result;
}
}
Subscribe to:
Posts (Atom)