zoukankan      html  css  js  c++  java
  • Chapter one

    1.strstr(字符串查找)

    对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1

    class Solution {
        /**
         * Returns a index to the first occurrence of target in source,
         * or -1  if target is not part of source.
         * @param source string to be scanned.
         * @param target string containing the sequence of characters to match.
         */
        public int strStr(String source, String target) {
            // write your code here
            if (source == null || target == null) {
                return -1;
            }
            for (int i = 0; i < source.length() - target.length() + 1; i++) {
                int j = 0;
                for (j = 0; j < target.length(); j++) {
                    if (target.charAt(j) != source.charAt(i + j)) {
                        break;
                    }
                }
                if (j == target.length()) {
                    return i;
                }
            }
            return -1;
        }
    }
    View Code

    思路:双重循环即可解决。注意第一重循环i的结束条件:source.length() - target.length() + 1。import java.lang.String

    2.subsets(子集)

    给定一个含不同整数(这些整数不重复)的集合,返回其所有的子集。子集中的元素排列必须是非降序的,解集必须不包含重复的子集。

    class Solution {
        /**
         * @param S: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
            // write your code here
            ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
            if (nums == null) {
                return results;
            }
            if (nums.length == 0) {
                results.add(new ArrayList<Integer>());
                return results;
            }
            Arrays.sort(nums);
            helper(results, new ArrayList<Integer>(), 0, nums);
            return results;
        }
        private void helper(ArrayList<ArrayList<Integer>> results,
                            ArrayList<Integer> subset,
                            int startIndex,
                            int[] nums) {
           //深度拷贝,不new的话最后results里面的每个元素都是相同的list,所以需要new来保存临时的list到results中。
            results.add(new ArrayList<Integer>(subset));
            for (int i = startIndex; i < nums.length; i++) {
                subset.add(nums[i]);
                helper(results, subset, i + 1, nums);
              //最后一个位置的元素删除,回溯到上一个节点
                subset.remove(subset.size() - 1);
            }
        }
    }
    View Code

    思路:题目中包含“所有可能.......”,90%使用深度优先搜索解决。注意由于子集中的元素排列是非降序,所以先排序。又由于题目返回的是[[...],[...],...]所以对nums == null(null指向一个空地址)和nums.length == 0(有一个对象但为空)分别处理,前一种情况直接返回results,后一种情况results.add(new ArrayList<Integer>())后再返回results.

    另一种解法: import java.util.ArrayList; import java.util.Arrays;

    class Solution {
        /**
         * @param S: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
            // write your code here
            ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
            ArrayList<Integer> subset = new ArrayList<Integer>();
            results.add(subset);
            if (nums ==  null || nums.length == 0) {
                return results;
            }
            Arrays.sort(nums);
            for (int i = 0; i < nums.length; i++) {
                ArrayList<ArrayList<Integer>> tempResults = new ArrayList<ArrayList<Integer>>(results);
                for (ArrayList<Integer> preResult : results) {
                    ArrayList<Integer> curResult = new ArrayList<Integer>(preResult);
                    curResult.add(nums[i]);
                    tempResults.add(curResult);
                }
                results = new ArrayList(tempResults);
            }
            return results;
        }
    }
    View Code

    3.subsets-ii(带重复元素的子集)

    class Solution {
        /**
         * @param nums: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] nums) {
            // write your code here
            ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
            if (nums == null) {
                return results;
            }
            if (nums.length == 0) {
                results.add(new ArrayList<Integer>());
                return results;
            }
            Arrays.sort(nums);
            helper(results, new ArrayList<Integer>(), 0, nums);
            return results;
        }
        private void helper(ArrayList<ArrayList<Integer>> results,
                            ArrayList<Integer> subset,
                            int startIndex,
                            int[] nums) {
            results.add(new ArrayList<Integer>(subset));
            for (int i = startIndex; i < nums.length; i++) {
                if (i != 0 && nums[i - 1] == nums[i] && i != startIndex) {
                    continue;
                }
                subset.add(nums[i]);
                helper(results, subset, i + 1, nums);
                subset.remove(subset.size() - 1);
            }
        }
    }
    View Code

    给定一个可能具有重复数字(这些整数可能重复)的列表,返回其所有可能的子集。子集中的每个元素都是非降序的,两个子集间的顺序是无关紧要的,解集中不能包含重复子集。

    思路:解集中不能包含重复的子集,所以使用“选代表法”去重。所以重复的数字都只选择第一个作为代表,例如{1,2(1),2(2)},规定{1,2(1)}和{1, 2(2)}重复。

    if (i != 0 && nums[i - 1] == nums[i] && i != startIndex) {
         continue;
    }
    解释:
    i != 0 防止数组越界
    nums[i - 1] == nums[i] && i != startIndex 判断nums[i]前一个跟目前这个是否一致
    i != startIndex 保证前一个没有被放进list: 如果nums[i - 1] 被放进list,则下一个startIndex是(i+1)也即(i-1+1)=i所以只需判断i != startIndex即可保证前一个没有被放进list
    View Code

    另一种解法:import java.util.ArrayList;  import java.util.Collections;

    class Solution {
        /**
         * @param nums: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] nums) {
            // write your code here
            ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
            ArrayList<Integer> subset = new ArrayList<Integer>();
            results.add(subset);
            if (nums ==  null || nums.length == 0) {
                return results;
            }
            Arrays.sort(nums);
            for (int i = 0; i < nums.length; i++) {
                ArrayList<ArrayList<Integer>> tempResults = new ArrayList<ArrayList<Integer>>(results);
                for (ArrayList<Integer> preResult : results) {
                    ArrayList<Integer> curResult = new ArrayList<Integer>(preResult);
                    curResult.add(nums[i]);
                    if (!tempResults.contains(curResult)) {
                        tempResults.add(curResult);
                    }
                }
                results = new ArrayList(tempResults);
            }
            return results;
        }
    }
    View Code

    4.permutations(全排列)

    给定一个数字列表,返回其所有可能的排列。你可以假设没有重复数字。

    class Solution {
        /**
         * @param nums: A list of integers.
         * @return: A list of permutations.
         */
        public List<List<Integer>> permute(int[] nums) {
            // write your code here
            ArrayList<List<Integer>> results = new ArrayList<List<Integer>>();
            if (nums == null) {
                return results;
            }
            if (nums.length == 0) {
                results.add(new ArrayList<Integer>());
                return results;
            }
            ArrayList<Integer> list = new ArrayList<Integer>();
            helper(results, list, nums);
            return results;
        }
        private void helper(ArrayList<List<Integer>> results,
                            ArrayList<Integer> list,
                            int[] nums) {
            if (list.size() == nums.length) {
                results.add(new ArrayList<Integer>(list));
            }
            for (int i = 0; i < nums.length; i++) {
                if (list.contains(nums[i])) {
                    continue;
                }
                list.add(nums[i]);
                helper(results, list, nums);
                list.remove(list.size() - 1);
            }
        }
    }
    View Code

    注意:无需排序

    5.permutations-ii(带重复元素的排列)

    给出一个具有重复数字的列表,找出列表所有不同的排列。

    class Solution {
        /**
         * @param nums: A list of integers.
         * @return: A list of unique permutations.
         */
        public List<List<Integer>> permuteUnique(int[] nums) {
            // Write your code here
            ArrayList<List<Integer>> results = new ArrayList<List<Integer>>();
            if (nums == null) {
                return results;
            }
            if (nums.length == 0) {
                results.add(new ArrayList<Integer>());
                return results;
            }
            ArrayList<Integer> list = new ArrayList<Integer>();
            Arrays.sort(nums);
            int[] visited = new int[nums.length];
            for (int i = 0; i < nums.length; i++) {
                visited[i] = 0;
            }
            helper(results, list, nums, visited);
            return results;
        }
        private void helper(ArrayList<List<Integer>> results,
                            ArrayList<Integer> list,
                            int[] nums,
                            int[] visited) {
            if (list.size() == nums.length) {
                results.add(new ArrayList<Integer>(list));
            }
            for (int i = 0; i < nums.length; i++) {
                if ((i != 0 && visited[i - 1] == 0 && nums[i - 1] == nums[i]) || visited[i] == 1) {
                    continue;
                }
                visited[i] = 1;
                list.add(nums[i]);
                helper(results, list, nums, visited);
                list.remove(list.size() - 1);
                visited[i] = 0;
            }
        }
    }
    View Code

    注意:先排序,使用visited数据记录该数字是否被访问,“选代表法“去重。

    if ( visited[i] == 1 || ( i != 0 && nums[i] == nums[i - 1]
                && visited[i-1] == 0)){
                    continue;
    }
    上面的判断主要是为了去除重复元素影响。
    比如,给出一个排好序的数组,[1,2,2],那么第一个2和第二2如果在结果中互换位置, 我们也认为是同一种方案,所以我们强制要求相同的数字,原来排在前面的,在结果 当中也应该排在前面,这样就保证了唯一性。所以当前面的2还没有使用的时候,就不应该让后面的2使用。
    View Code

    6.hash-function(哈希函数)

    在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数。一个好的哈希函数可以尽可能少地产生冲突。一种广泛使用的哈希函数算法是使用数值33,假设任何字符串都是基于33的一个大整数,比如:

    hashcode("abcd") = (ascii(a) * 33的3次方 + ascii(b) * 33的2次方 + ascii(c) *33 + ascii(d)) % HASH_SIZE 

                                  = (97* 33的3次方 + 98 * 33的2次方 + 99 * 33 +100) % HASH_SIZE

                                  = 3595978 % HASH_SIZE

    其中HASH_SIZE表示哈希表的大小(可以假设一个哈希表就是一个索引0 ~ HASH_SIZE-1的数组)。给出一个字符串作为key和一个哈希表的大小,返回这个字符串的哈希值。

    class Solution {
        /**
         * @param key: A String you should hash
         * @param HASH_SIZE: An integer
         * @return an integer
         */
        public int hashCode(char[] key, int HASH_SIZE) {
            // write your code here
            long ans = 0;
            for (int i = 0; i < key.length; i++) {
                ans = (ans * 33 + (int) key[i]) % HASH_SIZE;
            }
            return (int) ans;
        }
    };
    View Code

    7.strstr-ii【Rabin-Karp算法】【hard】

    在O(n + m)时间内实现strStr函数。

    public class Solution {
        /**
         * @param source a source string
         * @param target a target string
         * @return an integer as index
         */
        public int BASE = 1000000;
        public int strStr2(String source, String target) {
            // Write your code here
            if (source == null || target == null) {
                return -1;
            }
            int m = target.length();
            if (m == 0) {
                return 0;
            }
            //31^m
            int power = 1;
            for (int i = 0; i < m; i++) {
                power = (power * 31) % BASE;
            }
            //targetCode
            int targetCode = 0;
            for (int i = 0; i < m; i++) {
                targetCode = (targetCode * 31 + target.charAt(i)) % BASE;
            }
            //hashCode
            int hashCode = 0;
            for (int i = 0; i < source.length(); i++) {
                //abc + d
                hashCode = (hashCode * 31 + source.charAt(i)) % BASE;
                if (i < m - 1) {
                    continue;
                }
                //   i
                //abcd - a
                if (i >= m) {
                    hashCode = hashCode - (source.charAt(i - m) * power) % BASE;
                    if (hashCode < 0) {
                        hashCode += BASE;
                    }
                }
                //double check the string
                if (hashCode == targetCode) {
                    if (source.substring(i - m + 1, i + 1).equals(target)) {
                        return i - m + 1;
                    }
                }
            }
            return -1;
        }
    }
    View Code
  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/struggleli/p/6756364.html
Copyright © 2011-2022 走看看