1. 数组的全排列:

回溯法
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        LinkedList<List<Integer>> res = new LinkedList<List<Integer>>();
        if (nums == null || nums.length == 0)
            return res;
        Helper(res, new LinkedList<Integer>(), nums, new HashSet<Integer>());
        return res;
    }
    private void Helper(List<List<Integer>> res, List<Integer> curlist, int[] nums,
                       HashSet<Integer> set){
        if (curlist.size() == nums.length)
            res.add(new LinkedList<Integer>(curlist));
        else{
            for (int i = 0; i < nums.length; i++){ //对每个数而言
                if (set.contains(nums[i]))
                    continue;
//加数
                curlist.add(nums[i]);
                set.add(nums[i]);
                Helper(res, curlist, nums, set);  //下层的执行完,要把刚刚加进的数字弹出
//删数
                set.remove(nums[i]);
                int last = curlist.size() - 1;
                curlist.remove(last);
            }
        }
    }
}

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
        if (nums == null || nums.length == 0)
            return res;
        Helper(nums, res, new ArrayList<Integer>(), new HashSet<Integer>());
        return res;
    }
    private void Helper(int[] nums, ArrayList<List<Integer>> res, ArrayList<Integer> curlist,
                       HashSet<Integer> set){
        if (nums.length == curlist.size())
            res.add(new ArrayList<Integer>(curlist));
        else{
            for (int i = 0; i < nums.length; i++){
                if (set.contains(nums[i]))
                    continue;
                set.add(nums[i]);
                curlist.add(nums[i]);
                Helper(nums, res, curlist, set);
                set.remove(nums[i]);
                curlist.remove(curlist.size() - 1);
            }
        }
    }
}


2. 去重的全排列:

先排序  然后只需要在每个元素入数组之前判断:这个索引之前没用过&&这个数和上个数不一样
class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        if (nums == null || nums.length == 0)
            return null;
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Helper(nums, new boolean[nums.length], new LinkedList<Integer>(), res);
        return res;
    }
    private void Helper(int[] nums, boolean[] used, List<Integer> curlist, List<List<Integer>> res){
        if (curlist.size() == nums.length)
            res.add(new ArrayList<Integer>(curlist));
        else{
            int pre = nums[0] - 1;  //这个目的: 记录前一个数
            for (int idx = 0; idx < nums.length; idx ++){
                if (used[idx] == false && (nums[idx] != pre)) {
                    //索引没被用过,而且索引上的数字和前一个数不一样
                    pre = nums[idx];
                    curlist.add(nums[idx]);
                    used[idx] = true;
                    Helper(nums, used, curlist, res);
                    curlist.remove(curlist.size() - 1);
                    used[idx] = false;
                }
            }
        }
    }
}

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        if (nums == null || nums.length == 0)
            return null;
        Arrays.sort(nums);
        ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
        Helper(res, nums, new boolean[nums.length], new ArrayList<Integer>());
        return res;
    }
    private void Helper(ArrayList<List<Integer>> res, int[] nums, boolean[] use, 
                       ArrayList<Integer> curlist){
        if (curlist.size() == nums.length)
            res.add(new ArrayList<Integer>(curlist));
        else{
            int pre = nums[0] - 1;
            for (int i = 0; i < nums.length; i++){
                if (use[i] == false && pre != nums[i]){
                    pre = nums[i];
                    use[i] = true;
                    curlist.add(nums[i]);
                    Helper(res, nums, use, curlist);
                    curlist.remove(curlist.size() - 1);  //往上回溯时候  去掉后面的尾巴
                    use[i] = false;
                }
            }
        }
    }
}

3. 最长回文串:

class Solution {
    public int longestPalindrome(String s) {
        if(s == null || s.length() == 0)
            return 0;
        int[] count = new int[128];
        int res = 0;
        for (char c : s.toCharArray()){
            count[c] ++;
        }
        
        for (int val : count){
            res += val/2 *2;
            if (val%2 == 1 && res%2 == 0)  //如果想当中心
                res++;
        }
        return res;
    }
}

4. 最长回文子串:

中心拓展法,对每个字母进行中心拓展。
class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1)
            return "";
        int start = 0, end = 0;
        int len = 0;
        for(int i = 0; i < s.length(); i++){
            int len1 = expand(s, i, i);
            int len2 = expand(s, i, i+1);
            len = Math.max(len1, len2);
            if (len > (end - start)){
                start = i - (len - 1)/2;
                end = i + (len/2);
            }
        }
        
        return s.substring(start,end + 1);
    }
    
    private int expand(String s, int l, int r){
        int i = l, j = r;
        while(i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)){
            i --;
            j ++;
        }
        return j - i - 1;
    }
}

5. 二叉树展开为链表

后序递归,先右后左。
class Solution {
    TreeNode pre = null;
    public void flatten(TreeNode root) {
        if (root == null)
            return;
        flatten(root.right);
        flatten(root.left);
        root.right = pre;
        root.left = null;
        pre = root;
    }
}

6. 最长递增子序列:

动态规划,
public class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        int[] dp = new int[nums.length];
        dp[0] = 1;
        int maxans = 1;
        for (int i = 1; i < dp.length; i++) {
            int maxval = 0;
            for (int j = 0; j < i; j++) {          //对i之前的数遍历:如果i比j上的数大,那就看maxval能不能取更大的
                if (nums[i] > nums[j]) {
                    maxval = Math.max(maxval, dp[j]);  
                }
            }
            dp[i] = maxval + 1;
            maxans = Math.max(maxans, dp[i]);             //每个i结束,都看看能不能当最大的
        }
        return maxans;
    }
}
//我的方法:
class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0)
            return 0;
        int[] dp = new int[nums.length];
        dp[0] = 1;
        int res = 1;
        for (int i = 1; i < nums.length; i++){
            int maxFori = 0;
            for (int j = 0; j < i; j++){
                if(nums[i] > nums[j])
                    maxFori = Math.max(maxFori, dp[j]);
            }
            dp[i] = maxFori + 1;
            res = Math.max(res, dp[i]);
        }
        
        return res;
    }
}

7. 最长公共子数组:
从后往前
class Solution {
    public int findLength(int[] A, int[] B) {
        int ans = 0;
        int[][] memo = new int[A.length + 1][B.length + 1];
        //从后往前
        for (int i = A.length - 1; i >= 0; --i) {
            for (int j = B.length - 1; j >= 0; --j) {
                if (A[i] == B[j]) {
                    memo[i][j] = memo[i+1][j+1] + 1;
                    if (ans < memo[i][j])
                        ans = memo[i][j];
                }
            }
        }
        return ans;
    }
}

8. 快速幂:

class Solution {
    public double myPow(double x, int n) {
        long N = n;
        if (N < 0) {
            x = 1 / x;
            N = -N;
        }
        double ans = 1;
        double current_product = x;
        for (long i = N; i > 0; i /= 2) {
            if ((i % 2) == 1) {
                ans = ans * current_product; //注意这里:不管n是奇数还是偶数,都会走这一步,因为最后i都是1,如果n是奇数,那么就在第一步时候多乘个自己
            }
            current_product = current_product * current_product;
        }
        return ans;
    }
};

9. 合并k个有序链表

使用优先队列
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0)
            return null;
        PriorityQueue<ListNode> qu = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                if (o1.val < o2.val) return -1;
                else if (o1.val == o2.val) return 0;
                else return 1;
            }
        });
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        for (ListNode node: lists){ //先把头放进去
            if (node != null)
                qu.add(node);
        }
        //出队  下一个不空入队
        while(!qu.isEmpty()){
            p.next = qu.poll();
            p = p.next;
            if (p.next != null) qu.add(p.next);
        }
        return dummy.next;
    }
}