• Hash Table Three


     (1)Happy Number

    解题思路:使用HashSet,注意HashSet中的元素不能重复,所以不是happy number的数字要无限循环,一定要重复,就会返回false.

    代码如下:

     1 public class Solution {
     2     public boolean isHappy(int n) {
     3         Set<Integer> set = new HashSet<>();
     4         int sum, remain;
     5         while (set.add(n)) {
     6             sum = 0;
     7             while (n > 0) {
     8                 remain = n % 10;
     9                 sum += remain * remain;
    10                 n /= 10;
    11             }
    12             if (sum == 1) {
    13                 return true;
    14             } else {
    15                 n = sum;
    16             }
    17         }
    18         return false;
    19     }
    20 }
    View Code

    注意:while(set.add(n))这个判断条件。当不是happy number的数字无限循环时一定会重复,就不能继续加入就返回false.

    (2)Find All Anagrams in a String【理解不透】

    代码如下:

     1 public class Solution {
     2     public List<Integer> findAnagrams(String s, String p) {
     3         List<Integer> list = new ArrayList<>();
     4     if (s == null || s.length() == 0 || p == null || p.length() == 0) return list;
     5     int[] hash = new int[256]; //character hash
     6     //record each character in p to hash
     7     for (char c : p.toCharArray()) {
     8         hash[c]++;
     9     }
    10     //two points, initialize count to p's length
    11     int left = 0, right = 0, count = p.length();
    12     while (right < s.length()) {
    13         //move right everytime, if the character exists in p's hash, decrease the count
    14         //current hash value >= 1 means the character is existing in p
    15         if (hash[s.charAt(right)] >= 1) {
    16             count--;
    17         }
    18         hash[s.charAt(right)]--;
    19         right++;
    20         //when the count is down to 0, means we found the right anagram
    21         //then add window's left to result list
    22         if (count == 0) {
    23             list.add(left);
    24         }
    25         //if we find the window's size equals to p, then we have to move left (narrow the window) to find the new match window
    26         //++ to reset the hash because we kicked out the left
    27         //only increase the count if the character is in p
    28         //the count >= 0 indicate it was original in the hash, cuz it won't go below 0
    29         if (right - left == p.length() ) {
    30             if (hash[s.charAt(left)] >= 0) {
    31                 count++;
    32             }
    33             hash[s.charAt(left)]++;
    34             left++;
    35         }
    36     }
    37         return list;
    38     }
    39 }
    View Code

    解题思路:

    使用滑动窗口,使得时间复杂度为为O(n),这就是算法的力量!

    算法介绍:

    (1)count= p.length(),用来表示目前窗口中的字符和p的差异度(由于窗口最大时(为p.length())才有可能使count为0,所以count为0时窗口中的字符与p为Anagrams)。count差异度的含义:一开始窗口左右指针都指向第一个,所以差异度最大为p.length();当窗口中进来一个p中有的字符,差异度就减一,出去一个p中有的差异度就增一;至于进来或出去的是p中没有的,则count不变,反正窗口的最大值也不过是p.length()。

    (2)窗口的左右两个指针:left和right,分别指向窗口的左端和右端。

    滑动窗口具体操作:

    先滑动右指针,

    1.1 加进来的字符如果该字符在数组hash的计数中大于等于一意味着该字符在p中出现,则count减一,否则不做操作,

    1.2无论在不在p中出现,数组hash该字符相应位置计数都减一。

    1.3如果count为0,则将此时的left值加入到list中。

    判断如果窗口长度到达p.length(),开始滑动左指针:

    2.1被踢出窗口的那个字符如果在数组hash的计数中非负意味着原来在p中出现,此时要踢出,则差异度count增一,不在则不做操作。

    2.2无论在不在数组hash该字符相应位置计数都加一

    3.上面1.1和2.1操作的原理:hash中的记录的数据是代表p中含有的的每个字符的数量去掉当前窗口中存在的p字符串中每个字符的数量,一开始窗口大小为0,啥都不存在,自然hash中记录的就是全部p中含有的的每个字符的数量,如果窗口中有一个,则hash相应的记录中就少一个。如果窗口中多包含一个p中没有的(或者包含的某一个字符的数量比p中有的还多),那么这时候,hash中相应的记录值就会变成负数,代表当前窗口中包含相应字符的“多余”的数量。

          所以当进来一个的时候,如果相应记录为非负,那么这个进入是有意义的,则差异度(count)减一;当出去一个的时候,如果相应记录为非负,那么这个出去是有意义的,则差异度(count)加一。

    4.hash用到哈希表思想,用来记录p中每一种字符分别有多少个。

    (3)Bulls and Cows

    代码如下:

     1 public class Solution {
     2     public String getHint(String secret, String guess) {
     3         int[] count = new int[10];
     4         int bulls = 0;
     5         int cows = 0;
     6         for (int i = 0; i < secret.length(); i++) {
     7             int s = secret.charAt(i) - '0';
     8             int g = guess.charAt(i) - '0';
     9             if (s == g) {
    10                 bulls++;
    11             } else {
    12                 if (count[s] < 0) {
    13                     cows++;
    14                 }
    15                 if (count[g] > 0) {
    16                     cows++;
    17                 }
    18                 count[s]++;
    19                 count[g]--;
    20             }
    21         }
    22         return bulls + "A" + cows + "B";
    23     }
    24 }
    View Code

    解题思路:

    使用一个数组记录数字的出现,在secret中出现增加计数,在guess中出现减少计数。使用for循环遍历一次,如果s和g出现完全匹配,bulls计数加一.否则,如果此时s的计数小于零,说明guess中已有该数字,cows加一。如果此时g的计数大于零,说明secret中已有该数字,cows加一。然后s计数加一,g计数减一。

    (4)Isomorphic Strings

    解题思路一:主要想法是存储两个字符串中当前(第i个)字符的最后出现的位置。如果先前存储的位置不同,则他们同时出现在当前第i个位置是不可能的,故返回false。

    代码如下:

     1 public class Solution {
     2     public boolean isIsomorphic(String s1, String s2) {
     3         int[] m = new int[512];
     4         for (int i = 0; i < s1.length(); i++) {
     5             if (m[s1.charAt(i)] != m[s2.charAt(i) + 256]) {
     6                 return false;
     7             }
     8             m[s1.charAt(i)] = m[s2.charAt(i) + 256] = i + 1;
     9         }
    10         return true;
    11     }
    12 }
    View Code

    解题思路二:使用一个哈希表map维护两个字符串中字符的映射关系,同时用一个set保存映射的值。(s[i], t[i]),如果s[i]键没有在map中出现过并且t[i]没有在set中出现过,就加入到映射关系中。t[i]值已经出现过,说明是多对一映射,不符合返回false。s[i]键如果已经出现过,设为s[k],对应的映射值为t[k]),即s[i]==s[k],则找出s[k]的对对应值t[k],如果t[i]!=t[k],说明一个同一个字符存在两个不同的映射,两个字符串不是同构的,返回false,继续处理下一个字符,直到结束。 

    代码如下:

     1 public class Solution {       
     2     public boolean isIsomorphic(String s, String t) {   
     3         Map<Character, Character> map = new HashMap<Character, Character>();  
     4         Set<Character> set = new HashSet<Character>();  
     5           
     6         for(int i=0; i<s.length(); i++) {  
     7             char c1 = s.charAt(i);  
     8             char c2 = t.charAt(i);  
     9               
    10             if(map.containsKey(c1)) {  
    11                 if(map.get(c1) != c2) return false;  
    12             } else {  
    13                 if(set.contains(c2)) return false;  
    14                 else {  
    15                     map.put(c1, c2);  
    16                     set.add(c2);  
    17                 }  
    18             }  
    19         }  
    20         return true;  
    21     }  
    22 }  
    View Code
  • 相关阅读:
    Uploadify404无效链接
    java开发SSM框架的搭建(SpringMVC+Spring+MyBatis)
    PHP文件处理--操作文件
    机器学习01-kNN邻近算法
    多校 hdu
    iOS中OC给Category加入属性
    Wampserver 2.5 多网站配置方法
    c语言编写经验逐步积累4
    UVA 529 Addition Chains(迭代搜索)
    机器学习简史brief history of machine learning
  • 原文地址:https://www.cnblogs.com/struggleli/p/6164308.html
Copyright © 2020-2023  润新知