• 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
  • 相关阅读:
    C#中ConnectionStrings和AppSettings的区别
    VS2010 生成的程序在其他电脑上不运行的问题
    装修经验
    在Linux下安装rar for linux
    判断二叉搜索树的后序遍历序列
    二维数组中的查找某个数
    Spring MVC执行原理
    将二叉搜索树转换成一个排序的双向链表
    打印二叉树中所有分支之和等于某个数
    ObjectiveC中public、protected、private的使用[转]
  • 原文地址:https://www.cnblogs.com/struggleli/p/6756364.html
Copyright © 2020-2023  润新知