Leetcode之旅

20180530 又开始刷Leetcode,但愿能够坚持

  1. 两数之和
    两数之和,典型用空间换时间的问题,用HashMap可以有效减少时间复杂度。
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] re = new int[2];
        HashMap map = new HashMap<>();
        for (int i = 0; i < nums.length; i++)
            if (!map.containsKey(nums[i]))
                map.put(target - nums[i], i);
            else {
                re[0] = map.get(nums[i]);
                re[1] = i;
                break;
            }
        return re;
    }
}
  1. 两数相加
    链表练习题,最后忘了判断是否有进位,wa了一次。
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode p1 = l1;
        ListNode p2 = l2;
        ListNode re = new ListNode(0), head = re;
        int flag = 0, temp = 0;
        while (p1 != null && p2 != null) {
            temp = p1.val + p2.val + flag;
            flag = temp / 10;
            re.next = new ListNode(temp - flag * 10);
            p1 = p1.next;
            p2 = p2.next;
            re = re.next;
        }
        while (p1 != null) {
            temp = p1.val + flag;
            flag = temp / 10;
            re.next = new ListNode(temp - flag * 10);
            p1 = p1.next;
            re = re.next;
        }
        while (p2 != null) {
            temp = p2.val + flag;
            flag = temp / 10;
            re.next = new ListNode(temp - flag * 10);
            p2 = p2.next;
            re = re.next;
        }
        if (flag == 1)
            re.next = new ListNode(1);
        return head.next;
    }
}
  1. 无重复字符的最长子串 [推荐]
    一开始想用HashMap节省时间,坑了自己好久,应该先在脑子里想清楚思路和细节,再决定用什么数据结构。
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int max = 0, count = 0, mark = 0;
        for (int i = 0; i < s.length(); i++) {
            count++;
            for (int j = mark; j < i; j++) {
                if (s.charAt(i) == s.charAt(j)) {
                    count--;
                    mark = j + 1;
                    max = count > max ? count : max;
                    count = i - j;
                    break;
                }
            }
        }
        max = count > max ? count : max;
        return max;
    }
}
  1. 最长回文
    字符串操作题,要加加减减的逻辑,以免出界
class Solution {
    public String longestPalindrome(String s) {
        int max = 0, start = 0, end = 0;
        for (int i = 0; i < s.length(); i++) {
            int offset = 0;
            // mode 1
            while (i - offset >= 0) {
                if ((i + offset < s.length()) && (s.charAt(i - offset) == s.charAt(i + offset)))
                    offset++;
                else
                    break;
            }
            // max = max > offset * 2 + 1 ? max : offset * 2 + 1;
            if (max < offset * 2 - 1) {
                max = offset * 2 - 1;
                start = i + 1 - offset;
                end = i - 1 + offset;
            }
            // mode 2
            offset = 0;
            while (i - offset >= 0)
                if ((i + 1 + offset < s.length()) && (s.charAt(i - offset) == s.charAt(i + 1 + offset)))
                    offset++;
                else
                    break;
            if (max < offset * 2) {
                max = offset * 2;
                start = i + 1 - offset;
                end = i + offset;
            }
        }
        return s.substring(start, end + 1);
    }
}

6.Z字形变换
基本字符串操作题,注意循环次数和防御性条件即可

class Solution {
    public String convert(String s, int numRows) {
        if (s.length() == 0 || numRows == 1) 
            return s;
        StringBuffer sb = new StringBuffer();
        int circleLength = (numRows - 1) * 2;
        for (int j = 0; j * circleLength < s.length(); j++)
            sb.append(s.charAt(j * circleLength));
        for (int i = 1; i < numRows - 1; i++) {
            for (int j = 0; j * circleLength < s.length(); j++) {
                int mark = j * circleLength + i;
                if (mark < s.length())
                    sb.append(s.charAt(mark));
                mark = (j + 1) * circleLength - i;
                if (mark < s.length())
                    sb.append(s.charAt(mark));
            }
        }
        for (int j = 0; j * circleLength < s.length(); j++) {
            int mark = j * circleLength + numRows - 1;
            if (mark < s.length())
                sb.append(s.charAt(mark));
        }
        return sb.toString();
    }
}

7.翻转整数
题目里说假设环境只能存32位int,想了半天只能用try catch处理溢出了,一搜发现大家都用long……

后来想出了以下溢出判断方法

(c * 10) + t <= Integer.MAX_VALUE ==> c <= (Integer.MAX_VALUE - t) / 10
-(c * 10) - t >= Integer.MIN_VALUE ==> c <= - (Integer.MIN_VALUE + t) / 10
class Solution {
    public int reverse(int x) {
        boolean isPositive = true;
        if (x < 0)
            isPositive = false;
        StringBuilder sb = new StringBuilder(String.valueOf(Math.abs(x)));
        String re = (isPositive ? "" : "-") + sb.reverse().toString();
        int i;
        try {
            i = Integer.valueOf(re).intValue();
        } catch (NumberFormatException e) {
            i = 0;
        }
        return i;
    }
}
class Solution {
    public int reverse(int x) {
        boolean isNeg = x < 0;
        if (isNeg) x = -x;
        long l = 0;
        while (x > 0) {
            l = l * 10 + x % 10;
            x = x / 10;
        }
        if (isNeg) l = -l;
        if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE)
            l = 0;
        return (int) l;
    }
}
  1. 字符串转整数 [推荐]
    注意溢出处理
class Solution {
    public int myAtoi(String str) {
        int index = 0;
        long l = 0;
        char x = 0;
        boolean isNeg = false;
        for (; index < str.length(); index++) {
            x = str.charAt(index);
            if (x != ' ')
                break;
        }
        if (x == '+' || x == '-') {
            isNeg = x == '-';
            ++index;
            if (index >= str.length())
                return 0;
            x = str.charAt(index);
        }
        while (index < str.length()) {
            x = str.charAt(index);
            if (x < '0' || x > '9')
                break;
            l = l * 10 + (x - '0');
            if (isNeg && -l < Integer.MIN_VALUE)
                return Integer.MIN_VALUE;
            if (!isNeg && l > Integer.MAX_VALUE)
                return Integer.MAX_VALUE;
            index++;
        }
        if (isNeg) l = -l;
        return (int) l;
    }
}

9.回文数
送的

class Solution {
    public boolean isPalindrome(int x) {
        if (x < 0) return false;
        String t = String.valueOf(x);
        int len = t.length();
        for (int i = 0; i < len / 2; i++)
            if (t.charAt(i) != t.charAt(len - i - 1))
                return false;
        return true;
    }
}

11.盛最多数的容器 [推荐]
注意到只有运动较短侧,才可能提升容量,那么这题就解决了

class Solution {
    public int maxArea(int[] height) {
        int left = 0, right = height.length - 1, max = 0;
        while (left < right) {
            int lh = height[left], rh = height[right];
            int temp = (lh < rh ? lh : rh) * (right - left);
            max = max > temp ? max : temp;
            if (lh > rh)
                right--;
            else 
                left++;
        }
        return max;
    }
}
  1. 整数转罗马数
    纯考验细心
class Solution {
    public String intToRoman(int num) {
        int rep = num / 1000;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rep; i++)
            sb.append('M');
        num -= rep * 1000;
        rep = num / 100;
        if (rep == 9)
            sb.append("CM");
        else if (rep > 4) {
            sb.append('D');
            for (int i = 0; i < rep - 5; i++)
                sb.append('C');
        } else if (rep == 4) 
            sb.append("CD");
        else 
            for (int i = 0; i < rep; i++)
                sb.append('C');
        num -= rep * 100;
        rep = num / 10;
         if (rep == 9)
            sb.append("XC");
        else if (rep > 4) {
            sb.append('L');
            for (int i = 0; i < rep - 5; i++)
                sb.append('X');
        } else if (rep == 4) 
            sb.append("XL");
        else 
            for (int i = 0; i < rep; i++)
                sb.append('X');
        num -= rep * 10;
        rep = num;
         if (rep == 9)
            sb.append("IX");
        else if (rep > 4) {
            sb.append('V');
            for (int i = 0; i < rep - 5; i++)
                sb.append('I');
        } else if (rep == 4) 
            sb.append("IV");
        else 
            for (int i = 0; i < rep; i++)
                sb.append('I');
        return sb.toString();
    }
}
  1. 罗马转整数
    网上看了别人的代码,还是比if-else省力不少的,多多观察规律总有好处
class Solution {
    public int romanToInt(String s) {
        HashMap map = new HashMap() {{
            put('I', 1); put('V', 5); put('X', 10); put('L', 50);
            put('C', 100); put('D', 500); put('M', 1000);
        }};
        int re = 0;
        for (int i = 0; i < s.length(); i++) {
            if (i + 1 < s.length() && map.get(s.charAt(i)) < map.get(s.charAt(i + 1)))
                re -= map.get(s.charAt(i));
            else
                re += map.get(s.charAt(i));
        }
        return re;
    }
}
  1. 最长公共前缀
    最长子串的无限弱化版,注意array.length, string.length(), list.size()
class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs.length == 0 || strs[0].length() == 0) 
            return "";
        int mark = 0;
        while (mark < strs[0].length()) {
            char t = strs[0].charAt(mark);
            for (int j = 1; j < strs.length; j++) {
                if (mark >= strs[j].length() || t != strs[j].charAt(mark))
                    return strs[0].substring(0, mark);
            }
            mark++;
         }
         return strs[0].substring(0, mark);        
    }
}
  1. 三数之和
    题很简单,坑很多,比如重复值处理
class Solution {
    public List> threeSum(int[] nums) {
        List> re = new ArrayList>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 2; i++) {
            int m1 = i + 1, m2 = nums.length - 1;
            while (m1 < m2) 
                if (nums[m1] + nums[m2] > -nums[i])
                    m2--;
                else if (nums[m1] + nums[m2] < -nums[i])
                    m1++;
                else {
                    List list = Arrays.asList(nums[i],nums[m1],nums[m2]);
                    if (!re.contains(list))
                        re.add(list); 
                    m1++;
                    m2--;
                }
            while (i < nums.length - 3 && nums[i] == nums[i + 1])
                i++;
        }
        return re;
    }
}
  1. 最接近的三数之和
    与三数之和类似,通过排序减低时间复杂度
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        List re = new ArrayList();
        int diff = Integer.MAX_VALUE, sum = 0;
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 2; i++) {
            int m1 = i + 1, m2 = nums.length - 1;
            while (m1 < m2) {
                int tsum = nums[i]+nums[m1]+nums[m2];
                int tdiff = Math.abs(tsum - target);
                if (tdiff < diff) {
                    diff = tdiff;
                    sum = tsum;
                }
                if ( tsum > target ) 
                    m2--;
                else 
                    m1++;
            } 
        }
        return sum;
    }
}
  1. 电话号码字母
    又是无聊题
class Solution {
    public List letterCombinations(String digits) {
        ArrayList res = new ArrayList();
        if (digits.equals("")) return res;
        res.add("");
        HashMap map = new HashMap(){{
            put("0", " ");put("1", "");put("2", "abc");put("3", "def");put("4", "ghi");
            put("5", "jkl");put("6", "mno");put("7", "pqrs");put("8", "tuv");put("9", "wxyz");
        }};
        String[] ins = digits.split("");
        for(String in: ins) {
            ArrayList tempList = new ArrayList();
            String str = map.get(in);
            String[] chs = str.split(""); 
            for (String re: res)
                for (String ch: chs)
                    tempList.add(re+ch);
            res = tempList;
        }
        return res;
    }
}
  1. 删除链表的倒数第N个数
    链表操作题,自己加一个链表头会极大减少复杂度
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head.next == null)
            return null;
        ListNode start = new ListNode(0), p1 = start, p2 = start;
        start.next = head;
        int cnt = 0;
        while (p1.next != null) {
            p1 = p1.next;
            p2 = p2.next;
            cnt++;
            if (cnt <= n)
                p2 = start;
        }
        p2.next = p2.next.next;
        return start.next;
    }
}
  1. 有效的括号 [推荐]
    感觉自己写得太复杂,难过
class Solution {
    public boolean isValid(String s) {
        int m = 0, len = s.length();
        if (len % 2 != 0)
            return false;
        Map map = new HashMap(){{
            put('(', ')');put('[', ']');put('{', '}');
        }};
        Stack stack = new Stack();
        while (m < len) {
            Character c = s.charAt(m);
            if (map.containsKey(c))
                stack.push(c);
            else if (stack.isEmpty() || c != map.get(stack.pop()))
                return false;
            m++;
        }
        if (stack.isEmpty())
            return true;
        else
            return false;
    }
}
  1. Generate Parentheses
    先放右边,再放左边
class Solution {
    public List generateParenthesis(int n) {
        List re = new ArrayList();
        genPar(re, "", n, 0);
        return re;
    }
    
    private void genPar(List re, String str, int le, int ri) {
        if (le == 0 && ri == 0) {
            re.add(str);
            return;
        }
        
        if (ri > 0)
            genPar(re, str + ")", le, ri - 1);
        if (le > 0)
            genPar(re, str + "(", le - 1, ri + 1);
    }
}

21.23. 合并n个有序列表
21是23的特例,而23是最简单的困难题吧……

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int size = lists.length, cnt = 0;
        ListNode h = new ListNode(0), p = h;
        for (int i = 0; i < size; i++)
            if (lists[i] == null)
                cnt++;
        while (cnt < size) {
            int min = Integer.MAX_VALUE, mark = 0;
            for (int i = 0; i < size; i++)
                if (lists[i] != null && lists[i].val < min) {
                    min = lists[i].val;
                    mark = i;
                } 
            p.next = lists[mark];
            lists[mark] = lists[mark].next;
            p = p.next;
            if (lists[mark] == null)
                cnt++;
        }
        return h.next;
    }
}

24.25. Reverse List in k-Group
24是25的特例,就不分开写了,连标题真的要特别注意初始化和终止条件,注意是否越界、是否符合要求

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if (k <= 1 || head == null)
            return head;
        ListNode start = new ListNode(0), p1 = head, p2 = head, pt = head, ph = head, ptail = start;
        start.next = head;
        int cnt = 1;
        while (p2 != null) {
            if (cnt >= k) {
                ph = p2.next;
                while (p1 != p2) {
                    pt = p1.next;
                    p1.next = ph;
                    ph = p1;
                    p1 = pt; 
                }
                p2.next = ph;
                ptail.next = p2;
                while (cnt-- > 0)
                    ptail = ptail.next;
                cnt = 1;
                p1 = p2 = ptail.next;
            } else {
                p2 = p2.next;
                cnt++;
            }
        }
        return start.next;
    }
}
  1. Remove Duplicates from Sorted Array
    太水了
class Solution {
    public int removeDuplicates(int[] nums) {
        int i = 1, len = nums.length, cnt = 1;
        if (len == 0)
            return 0;
        for (; i < len; i++)
            if (nums[i - 1] != nums[i])
                nums[cnt++] = nums[i];
        return cnt;
    }
}

27-28 太水,就不贴了

  1. Divide Two Integers [推荐]
    用位运算计算触发,也许会用到
class Solution {
    public int divide(int dividend, int divisor) {
        if (divisor == Integer.MIN_VALUE)
            if (dividend == divisor) return 1;
            else return 0;
        else if (divisor == -1 && dividend == Integer.MIN_VALUE)
            return Integer.MAX_VALUE;
        
        int a = Math.abs(dividend), b = Math.abs(divisor), res = 0;
        for (int x = 31; x >= 0; x--)
            if ((a >>> x) - b >= 0) {
                res += 1 << x;
                a -= b << x;
            }
        return (dividend > 0) == (divisor > 0) ? res : -res;
    }
}
  1. Next Permutation [推荐]
    这题比较有意思,找到规律后居然cover所有测试,而不需要 if 处理一些特例,数学真奇妙
class Solution {
    public void nextPermutation(int[] nums) {
        int len = nums.length, i = len - 2;
        while (i >= 0 && nums[i] >= nums[i + 1])
            i--;
        if (i >= 0) {
            int j = len - 1;             
            while(nums[j] <= nums[i]) j--;      
            swap(nums, i, j);                    
        }
        reserve(nums, i + 1, len - 1);
    }
    
    private void swap(int[] nums, int i, int j) {
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
    
    private void reserve(int[] nums, int i, int j) {
        while (i < j)
            swap(nums,i++,j--);
    }
}
  1. Search for a Range [推荐]
    二分查找的变形,我觉得这种经典算法的变形题比较有趣,考验基础掌握和灵活变通,且有一定的工程意义,而不是智力游戏。
class Solution {
    public static int[] searchRange(int[] nums, int target) {
        int[] re = new int[] {-1, -1};
        if (nums.length == 0)
            return re;
        int t = searchLo(nums, target, 0, nums.length - 1);
        if (t != -1) {
            re[0] = t;
            re[1] = searchHi(nums, target, 0, nums.length - 1);
        }
        return re;
    }
    
    private static int searchLo(int[] nums, int target, int lo, int hi) {
        if (nums[lo] == target)
            return lo;
        if (lo + 1 >= hi)
            if (nums[hi] == target)
                return hi;
            else
                return -1;
        int mi = (lo + hi) / 2;
        if (nums[mi] >= target)
            return searchLo(nums, target, lo, mi);
        else
            return searchLo(nums, target, mi, hi);
    }
    
    private static int searchHi(int[] nums, int target, int lo, int hi) {
        if (nums[hi] == target)
            return hi;
        if (lo + 1 >= hi)
            return lo;
        int mi = (lo + hi) / 2;
        if (nums[mi] <= target)
            return searchHi(nums, target, mi, hi);
        else
            return searchHi(nums, target, lo, mi);
    }
}

简化一点:

class Solution {
    public static int[] searchRange(int[] nums, int target) {
        int[] re = new int[] {-1, -1};
        if (nums.length == 0)
            return re;
        int t, tail = nums.length - 1;
        if (nums[0] == target)
            t = 0;
        else
            t = search(nums, target, 0, tail, true);
        if (t != -1) {
            re[0] = t;
            if (nums[tail] == target)
                re[1] = tail;
            else
                re[1] = search(nums, target, 0, tail, false);
        }
        return re;
    }
    
    private static int search(int[] nums, int target, int lo, int hi, boolean searchLow) {
        if (lo + 1 >= hi)
            if (searchLow)
                if (nums[hi] == target) return hi;
                else return -1;
            else
                if (nums[lo] == target) return lo;
                else return -1;
        
        int mi = (lo + hi) / 2;
        if ((searchLow && nums[mi] >= target) || (!searchLow && nums[mi] > target))
            return search(nums, target, lo, mi, searchLow);
        else
            return search(nums, target, mi, hi, searchLow);
    }
}
  1. Search Insert Position
    做完刚才那题,再写这题就很随意。
class Solution {
    public int searchInsert(int[] nums, int target) {
        int lo = 0, hi = nums.length - 1;
        if (hi == -1 || nums[lo] >= target)
            return 0;
        if (nums[hi] < target)
            return hi + 1;
        return bsInsert(nums, target, lo, hi);
    }
    
    private int bsInsert(int[] nums, int target, int lo, int hi) {
        int mi = (lo + hi) / 2;
        if (nums[mi] < target && nums[mi + 1] >= target)
            return mi + 1;
        
        if (nums[mi] >= target)
            return bsInsert(nums, target, lo, mi);
        else
            return bsInsert(nums, target, mi, hi);
    }
}
    1. CombinationSum
      就是个dfs,注意到排序去重即可
class Solution {
    public static List> combinationSum2(int[] candidates, int target) {
        List> res = new ArrayList>();
        if (candidates.length == 0)
            return res;
        List re = new ArrayList();
        boolean[] flags = new boolean[candidates.length];
        dfs(res,re,candidates,flags, target);
        return res;
    }
    
    private static void dfs(List> res, List re, int[] candidates, boolean[] flags, int target) {
        int sum = 0;
        for (Integer t: re)
            sum += t;
        if (sum == target && !res.contains(re)) {
            res.add(new ArrayList(re));
            return;
        } else if (sum > target)
            return;
        for (int i = 0, len = candidates.length; i < len; i++) 
            if (flags[i] == false && (re.size() == 0 || candidates[i] >= re.get(re.size() - 1))) {
                re.add(candidates[i]);
                flags[i] = true;
                dfs(res, re, candidates, flags, target);
                re.remove(re.size() - 1);
                flags[i] = false;
            }
    }
}

41 First Missing Positive [推荐]
将下标作为容器,是算法题里一种重要思路

class Solution {
    public int firstMissingPositive(int[] nums) {
        int i = 0;
        int len = nums.length;
        while (i 0 && nums[i] < len // careful with both barriers
                && nums[ nums[i] - 1 ] != nums[i])
                swap(nums, i, nums[i] - 1);
            else // brilliant 'else'
                i++;
        }
        
        i = 0;
        while (i

45 Jump Game II
这么水的DP居然是hard……看来最简单hard可以更新了

class Solution {
    public int jump(int[] nums) {
        int len = nums.length;
        if (len == 0)
            return 0;
        int[] min = new int[len];
        min[0] = 0;
        for (int i = 1; i < len; i++)
            min[i] = Integer.MAX_VALUE;
        for (int i = 0; i < len - 1; i++) {
            int steps = min[i] + 1;
            for (int j = 1; j <= nums[i]; j++) {
                int index = i + j;
                if (index < len && min[index] > steps)
                    min[index] = steps;
            }
        }
        return min[len - 1];
    }
}
  1. Permutation [推荐]
    两个亮点:直接把nums转成list传进去remove,add,会导致排列错序,以后还是用flag标记是否访问吧;居然要手动import!
import java.util.Map.Entry;

class Solution {
    public List> permute(int[] nums) {
        List> res = new ArrayList>();
        List re = new ArrayList();
        if (nums.length > 0) {
            Map map = new HashMap();
            for (int num: nums) {
                map.put(num, false);
            }
            dfs(res, re, map);
        }
        return res;
    }
    
    private void dfs(List> res, List re, Map map) {
        if (!map.values().contains(false)) {
            res.add(new ArrayList(re));
            return;
        }
            
        for (Entry entry: map.entrySet())
            if (!entry.getValue()) {
                entry.setValue(true);
                re.add(entry.getKey());
                dfs(res,re,map);
                entry.setValue(false);
                re.remove(entry.getKey());
            }
    }
}
  1. Permutation II
    为什么呢?
class Solution {
    public List> permuteUnique(int[] nums) {
        LinkedList> res = new LinkedList>();
        Arrays.sort(nums);
        dfs(nums, new LinkedList(), res, new boolean[nums.length]);
        return res;
    }
    
    private void dfs(int[] nums, LinkedList re, LinkedList> res, boolean[] visited) {
        int len = nums.length;
        if (re.size() == len) {
            res.add(new LinkedList(re));
            return;
        }
        
        for (int i = 0; i < len; i++) {
            if (visited[i] || (i-1 >= 0 && visited[i-1] && nums[i] == nums[i-1]))
                continue;
            
            visited[i] = true;
        re.add(nums[i]);
        dfs(nums, re, res, visited);
        re.remove(re.size()-1);
        visited[i] = false; 
        }
    }
}

48 Rotate Image
用笔推演旋转过程,不难发现坐标转换规律,但是写代码时不小心写错了两个地方,细心真是一件很难的事情。

class Solution {
    public void rotate(int[][] matrix) {
        int len = matrix.length;
        if (len <= 1)
            return;
        for (int i = 0, endi = len / 2; i < endi; i++)
            for (int j = 0, endj = len - 1 - i * 2; j < endj; j++) // forget to multiply 2 and i
                swap4(matrix, len, i + j, i); // forget to use i + j, i instead of i, j
    }

    private void swap4(int[][] m, int l, int i, int j) {
        int tempValue, lastValue = m[i][j], tempi, tempj;
        for (int k = 0; k < 4; k++) {
            tempi = i;
            tempj = j;
            i = tempj;
            j = l - 1 - tempi;
            tempValue = m[i][j];
            m[i][j] = lastValue;
            lastValue = tempValue;
        }
    }
}
  1. Group Anagram [推荐]
    没什么难度,看了discuss习得质数分桶法,牛b!
class Solution {
    public List> groupAnagrams(String[] strs) {
        int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103}; // careful with potential overflow
        List> res = new LinkedList<>();
        Map> map = new HashMap<>();
        for (String str: strs) {
            int key = 1;
            for (char c: str.toCharArray()) {
                key *= prime[c - 'a'];
            }
            List list;
            if (map.containsKey(key)) {
                list = map.get(key);
            } else {
                list = new LinkedList<>();
                map.put(key, list);
                res.add(list);
            }
            list.add(str);
        }
        return res;
    }
}
  1. Pow [推荐]
    位操作
class Solution {
    public double myPow(double x, int n) {
        if (n == Integer.MIN_VALUE)
            return 1/(myPow(x,Integer.MAX_VALUE)*x);
        boolean reverse = false;
        if (n < 0) {
            n = -n;
            reverse = true;
        }
        double res = 1;
        //for (int i = 0; i < 32; i++) {
        while (n>0) {
            if ((n&1) == 1) 
                res *= x;
            n = n >> 1;
            x *= x;
        }
        return reverse? 1/res:res;
    }
}

你可能感兴趣的:(Leetcode之旅)