Monday, February 26, 2018

102. Linked List Cycle

对于带环链表的检测,效率较高且易于实现的一种方式为使用快慢指针。快指针每次走两步,慢指针每次走一步,如果快慢指针相遇(快慢指针所指内存为同一区域)则有环,否 则快指针会一直走到NULL为止退出循环,返回false.

public boolean hasCycle(ListNode head) {
        // write your code here
        if (head == null || head.next == null) {
            return false;
        }
       
        ListNode slow = head;
        ListNode fast = head;
       
        fast = fast.next.next;
        while(slow != fast) {
            if(fast == null || fast.next == null) {
                return false;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
       
        return true;
    }

Sunday, February 25, 2018

170. Rotate List

Given a list, rotate the list to the right by k places, where k is non-negative.

Wrong solution 1:
public ListNode rotateRight(ListNode head, int k) {
        // write your code here
        if (head == null || head.next == null) {
            return head;
        }
        ListNode slow = head;
        ListNode fast = head;
        for (int i = 0; i < k; i++) {
            fast = fast.next;
        }
        
        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        fast.next = head;
        head = slow.next;
        slow.next = null;
        
        return head;

    }


WA

if k is greater than the length of the linked list, it needs to mod the length of the linked list


Solution 2:
  public ListNode rotateRight(ListNode head, int k) {
        // write your code here
        if (head == null || head.next == null) {
            return head;
        }
        ListNode slow = head;//new ListNode(0);
        //slow.next = head;
        ListNode fast = head;
        int length = getLength(head);
        for (int i = 0; i < (k % length); i++) {
            fast = fast.next;
        }
        
        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        fast.next = head;
        head = slow.next;
        slow.next = null;
        return head;
    }
    
    private int getLength(ListNode head) {
        int length = 0;
        ListNode dummy = head;
        while(dummy != null) {
            length++;
            dummy = dummy.next;
        }
        return length;
    }

    

35. Reverse Linked list

Reverse a linked list.



public ListNode reverse(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            ListNode temp = head.next;
            head.next = prev;
            prev = head;
            head = temp; 
        }
        
        return prev;

    }




96. Partition List

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.



Solution:

Create a small list and a large list.

Go through the linked list.

If the current node is smaller than x, we link it with the small list.

Otherwise we link the node with the large list.

Finally, we link the small list with the large list.



WA:
1->4->3->2->5->2->null
3
lcur.next = null;
加入后可行, 这个是为了避免产生环

public class Solution {
    /*
     * @param head: The first node of linked list
     * @param x: An integer
     * @return: A ListNode
     */
    public ListNode partition(ListNode head, int x) {
        // write your code here
        ListNode small = new ListNode(-1);
        ListNode scur  = small;
        ListNode large = new ListNode(-1);
        ListNode lcur  = large;
        ListNode dummy = head;
       
        while (dummy != null) {
            if(dummy.val < x){
                scur.next = dummy;
                scur = scur.next;
            } else {
                lcur.next = dummy;
                lcur = lcur.next;
            }
            dummy = dummy.next;
        }
       
        lcur.next = null; // avoid cycle
        scur.next = large.next;
        return small.next;
    }
}

Saturday, February 24, 2018

112. Remove Duplicates from Sorted List

/**
 * Definition for ListNode
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param head: head is the head of the linked list
     * @return: head of linked list
     */
    public ListNode deleteDuplicates(ListNode head) {
        // write your code here
        if (head == null || head.next == null){
            return head;
        }
       
        ListNode curr = head;
        while(curr.next != null) {
            int val = curr.val;
            if (curr.next.val == val) {
                curr.next = curr.next.next;
            } else {
                curr = curr.next;
            }
        }
       
        return head;
    }
}

165. Merge Two Sorted Lists

/**
 * Definition for ListNode.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int val) {
 *         this.val = val;
 *         this.next = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param l1: ListNode l1 is the head of the linked list
     * @param l2: ListNode l2 is the head of the linked list
     * @return: ListNode head of linked list
     */
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // write your code here
        if (l1 == null) {
            return l2;
        }
       
        if (l2 == null) {
            return l1;
        }
       
        // int val = l1.val < l2.val ? l1.val : l2.val;
        ListNode head = new ListNode(-1);
        ListNode dummy1 = l1;
        ListNode dummy2 = l2;
        ListNode dummy3 = head;

        // dummy != null 不是dummy.next != null
        while (dummy1 != null && dummy2 != null){
            if(dummy1.val < dummy2.val){
                dummy3.next = new ListNode(dummy1.val);
                dummy1 = dummy1.next;
            } else {
                dummy3.next = new ListNode(dummy2.val);
                dummy2 = dummy2.next;
            }
            dummy3 = dummy3.next;
        }
       
        // 如果是dummy.next == null 那就不会进入这个判断了
        if (dummy1 == null) {
            dummy3.next = dummy2;
        } else {
            dummy3.next = dummy1;
        }
       
        return head.next;
    }
}

Friday, February 23, 2018

174. Remove Nth Node From End of List

public class Solution {
    /*
     * @param head: The first node of linked list.
     * @param n: An integer
     * @return: The head of linked list.
     */
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // write your code here
        // slow is point before target, fast gonna reach the end of list
        ListNode slow = head;
        ListNode fast = head;
       
        // There is n nodes between slow and fast
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
       
        // Case: 1->null 1,  1->2->null 2
        if(fast == null) {
            head = head.next;
            return head;
        }
       
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
       
        if (slow == head) {
            head = head.next;
        } else {
            slow.next = slow.next.next;
        }
       
        return head;
    }
}


public class Solution {
    /**
     * @param head: The first node of linked list.
     * @param n: An integer.
     * @return: The head of linked list.
     */
    ListNode removeNthFromEnd(ListNode head, int n) {
        // write your code here
        if (head == null) {
            return head;
        }
        
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy.next;
        
        ListNode p1 = dummy;
        ListNode p2 = dummy;
        
        for (int i = 0; i < n; i++) {
            p1 = p1.next;
        }
        while (p1.next != null) {
            p1 = p1.next;
            p2 = p2.next;
        }
        p2.next = p2.next.next;
        
        return dummy.next;
    }
}

53. Next Permutation

Given a list of integers, which denote a permutation.
Find the next permutation in ascending order.

Solution:
From back to front, find the first index i that nums[i] < nums[i + 1].

From back to i, find the first index j that nums[j] > nums[i].

Swap nums[i] and nums[j].

Reverse nums[i + 1, end].

The time complexity is O(n) and the space complexity is O(1).



public class Solution {
    /**
     * @param nums: A list of integers
     * @return: A list of integers
     */
    public int[] nextPermutation(int[] nums) {
        // write your code here
        // int reverseIndex= -1;
        // for(int i = nums.length - 2; i >= 0; i--) {
        //     if(nums[i] <= nums[i+1]) {
        //         swap(nums, nums[i], nums[i+1]);
        //         reverseIndex = i+1;
        //         break;
        //     }
        // }
        
        
        int i = nums.length - 2;
        
        // 找到第一个降序的
        while (i >= 0 && nums[i+1] <= nums[i]) {
            i--;
        }
        
        
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= i && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1, nums.length-1);
        
        return nums;
    }
    
    void swap(int[] nums, int j, int k) {
        int temp = nums[j];
        nums[j] = nums[k];
        nums[k] = temp;
    }
    
    void reverse(int[] nums, int start, int end) {
        while(start < end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }
}

Wednesday, February 21, 2018

116. Jump Game

Question
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.

Thinking
读题
1. 无负数
2. 指向0

range = A[i] + i
target = A.length-1;

贪心Greedy:
最大的距离我们可以跳到
在可以跳到的任意位置, 设最大距离是 之前最大距离和我们现在能跳的最大距离 中大的一个

Greedy 在条件
1. 可以达到目前为止
下:获得最大的可以跳的距离

比较最大跳的距离 和 目标 得到结果

public class Solution {
    /*
     * @param A: A list of integers
     * @return: A boolean
     */
    public boolean canJump(int[] A) {
        // write your code here
        int maxReach = 0;
        int target = A.length - 1;
        
        for(int i = 0; i < A.length; i++){
            int range = A[i] + i;
            // check if current maxReach can reach i;
            if(maxReach >= i){
                maxReach = Math.max(range, maxReach);    
            }
            
        }
            
        return maxReach >= target ? true : false;
        
    }
    
}

182. Delete Digits

Question:
Given string A representative a positive integer which has N digits, remove any k digits of the number, the remaining digits are arranged according to the original order to become a new positive integer.
Find the smallest integer after remove k digits.
N <= 240 and k <= N,


Example
Given an integer A = "178542", k = 4
return a string "12"

Thinking

rest = N-k
find teh 

要让一个数尽量小,那么就要把小的数字尽量放到前面,如果前面有比它大的数字,那么就到把在它前面且比它大的数字都要删除掉,直到已经删掉k个数字,所以最后留下的是一个递增数列。同时要考虑一些特殊情况,比如前置0要去掉,以及如果遍历一遍之后发现删去的数不足k个,则删去最后的k-count个数。

1. 当stack不是空的时候
2. stack的top比现有的数大
3. 还未达到删除数
目的:选出倒序的k个最小数


然后需要一个temp stack 反转

如果没有达到k个数,res 的
ex: 12345 3
stack:1
rest:3-1


public class Solution {
    /*
     * @param A: A positive integer which has N digits, A is a string
     * @param l: Remove k digits
     * @return: A string
     */
    public String DeleteDigits(String A, int k) {
        // write your code here
        String res = "";
        if(A.length() == 0 || A == null) {
            return res;
        }
        
        Stack<Character> stack = new Stack<Character>();
        int count = 0;
        for(int i = 0; i < A.length(); i++) {
            char curt = A.charAt(i);
            
            // 
            // 1. 当stack不是空的时候
            // 2. stack的top比现有的数大
            // 3. 还未达到删除数
            // 尽可能选出倒序的k个最小数
            // 
            
            while(!stack.isEmpty() && stack.peek() > curt && count < k){
                stack.pop();
                count++;
            }
            stack.push(curt);
        }
        
        //反序stack
        Stack<Character> temp = new Stack<Character>();
        while(!stack.isEmpty()) {
            temp.push(stack.pop());
        }
        
        while(!temp.isEmpty()) {
            res = res + temp.pop();
        }
        
        // Case: count没有达到k个
        // ? 是不是直接substring k就行了
        if(count < k){
            int num = k - count;
            res = res.substring(0, res.length()-num); 
        }
        
        
        // Case: 最前面的0
        // count all the zeros in the result
        int i = 0;
        while(i < res.length() && res.charAt(i) == '0'){
            i++;
        }
        if(i == res.length()){
            res = "0";
        }else{
            res = res.substring(i);
        }

        return res;
        
    }
}


优化:
循环k次:
    删除[j] > [j+1]
删除前置0


StringBuilder sb = new StringBuilder(A);
        int i, j;
        for (i = 0; i < k; i++) {
            // 如果 [j] <= [j+1] 保留 并 j++
            for (j = 0; j < sb.length() - 1
                    && sb.charAt(j) <= sb.charAt(j + 1); j++) {
            }
            // 删除比后一个大的
            sb.delete(j, j + 1);
        }
        // 持续检查第一位如果是零删除
        while (sb.length() > 1 && sb.charAt(0)=='0'){
            sb.delete(0,1);
        }
        return sb.toString();



Tuesday, February 20, 2018

184. Largest Number

【题目】
Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.
Credits:
Special thanks to @ts for adding this problem and creating all test cases.
【题意】
给定一个数组,这些数连在一起可以组成一个大数,求能组成最大数。
如 [3, 30, 34, 5, 9] 能组成的最大数为 9534330。
由于组成的数可能非常大,用字符串返回。
【解法】
//不想听繁琐分析的课跳过直接看代码,代码中有注释
关键是确定每个数在最后结果中的先后位置,比较直观的是个位数越大的越靠前,如例子中9在5, 4, 3之前;
个位相同的再看十位,如例子中34应当在30之前;
难点是位数不等时,先后关系怎么确定?如例子中3应当放在30和34之前、之后还是中间?
结果是3放在了34和30中间,为什么呢?这是因为十位上的4比个位上3大,所以34在3之前,而十位上的0比个数上的3小,所以30在3之后。
这样貌似可以找到规律,就是对于那些有包含关系的数,如1234包含12,那么只需看1234比12多出的部分34比12大还是小。
通过这样的方法,貌似也可判断出个先后顺序。只是这样需要考虑的情况太复杂了,如565656和56……
//正解如下:
可以换一下思路,要想比较两个数在最终结果中的先后位置,何不直接比较一下不同组合的结果大小?
举个例子:要比较334的先后位置,可以比较334343的大小,而343334大,所以34应当在前。
这样,有了比较两个数的方法,就可以对整个数组进行排序。然后再把排好序的数拼接在一起就好了。


public class Solution {
    /*
     * @param nums: A list of non negative integers
     * @return: A string
     */
    public String largestNumber(int[] nums) {
        // write your code here
       String[] strs = new String[nums.length];
       for(int i = 0; i < nums.length; i++) {
           strs[i] = Integer.toString(nums[i]);
       }
       
       Arrays.sort(strs, new Cmp());
       StringBuilder sb = new StringBuilder();
       for(int i = 0; i < strs.length; i++) {
           sb.append(strs[i]);
       }
       
       String result = sb.toString();
       int index = 0;
       while(index < result.length() && result.charAt(index) == '0') {
           index++;
       }
       
       if(index == result.length()) {
           return "0";
       }
       return result.substring(index);
    }
    
    
}

class Cmp implements Comparator<String>{
    @Override
    public int compare(String a, String b) {
        String ab = a.concat(b);
        String ba = b.concat(a);
        return ba.compareTo(ab);
    }
}

4. Ugly Number

1*2(t2) 2*2 3*2 (t3)1*3 2*3 3*3 (t5)1*5 2*5 3*5 1*2 2*2(t2) 3*2 1*3(t3) 2*3 3*3 (t5)1*5 2*5 3*5 Solution: public int nthUglyNumbe...