HASH and leetcode questions

HASH and leetcode questions

Summary of HASH table knowledge points

To put it simply, it is the mapping of key-value pairs. Most of them have already been exposed. Here is a summary of Java HASH and how to apply. The HASH table can determine whether an element has appeared before. If the element has not appeared before, the element will be inserted into the HASH table to facilitate the next query.

There are currently three ways to implement HASH tables:

  1. array
  2. hashmap
  3. hashset (does not allow insertion of duplicate elements)

The overall implementation of the array is relatively simple. Here is an introduction to hashmap and hashset.

How to use HashMap

  1. HashMap definition: You can specify the type of key (Key) and value (Value).

    HashMap<KeyType, ValueType> hashMap = new HashMap<>();
    HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
    
  2. Add element: Use theput() method to add key-value pairs to the hash table.

    map.put(2,1);
    
  3. Get the element: Use the get() method to get the corresponding value by key.

    int value =  map.get(2);
    
  4. Delete element: Use theremove() method to delete the corresponding key-value pair by key.

    map.remove(2);
    
  5. Determine whether the key exists: Use thecontainsKey() method to check whether a key exists in the hash table.

    map.containsKey(2);
    
  6. Get the size of the hash table: Use the size() method to get the number of key-value pairs in the hash table.

    int n = map.size();
    
  7. Determine whether is empty: use the isEmpty() method to check whether hashmap is empty.

    map.isEmpty();
    
  8. Clearhashmap table: use clear() method to clearhashmap

    set.clear();
    

How to use HashSet

  1. HashSetDefinition: You can specify the key(Key) type, no value. Use the HashSet class to create oneHashSet for storage Elements of a specific type. is used to store a collection of unique elements.

    HashSet<ElementType> hashSet = new HashSet<>();
    HashSet<Integer> set = new HashSet<Integer>();
    
  2. Add element: Useadd() method to add specified element

    set.add(4);
    
  3. Delete element: Useremove() method to delete element

    set.remove(4);
    
  4. Determine whether the element exists: Usecontains() method to check whether the element exists

    set.contains(4);
    
  5. Getset table size: Usesize() method to get the number in the hash table.

    int n = set.size();
    
  6. Determine whether is empty: use the isEmpty() method to check whether hashset is empty.

    map.isEmpty();
    
  7. Clearset table: use clear() method to clearhashset

    set.clear();
    

Review questions

Valid allophones

topic:

Click on the question link

Given two strings*s* and *t*, write a function to determine whether *t* is*s* allophones.

**Note:** If the number of occurrences of each character in *s* and *t* is the same, it is called *s* and *t* are anagrams of each other.

Example 1:

输入: s = "anagram", t = "nagaram"
输出: true

Example 2:

输入: s = "rat", t = "car"
输出: false

hint:

  • 1 <= s.length, t.length <= 5 * 104
  • s and t contain only lowercase letters
Idea:
  • Since the string only contains lowercase characters, the implementation of the table can be simulated directly through the int arrayhash
  • The specific implementation is to first convert the string type into a character array type, and then traverse two arrays. One array counts the number of occurrences of each character from the forward direction, and the other array The array counts the number of occurrences of characters from reverse. Finally, traverse the array again to determine whether a symbol other than 0 appears. If it does, it means that the conditions are not met.
Code:
class Solution {
    
    
    public boolean isAnagram(String s, String t) {
    
    
        //转为字符数组
        char[] sstr = s.toCharArray();
        char[] tstr = t.toCharArray();
        int slen = sstr.length;
        int tlen = tstr.length;

        //长度不同,不符合条件
        if(slen != tlen) return false;
        int hash[] = new int[26];

        //正向和反向统计出现的次数
        for(int i = 0; i < slen; i++){
    
    
            hash[sstr[i]-'a']++;
            hash[tstr[i]-'a']--;
        }

        //hash表判断
        for(int i = 0; i < 26; i++){
    
    
            if(hash[i] != 0) return false;
        }
        return true;
    }
}

Intersection of two arrays

topic:

Click on the question link

  • Given two arraysnums1 and nums2, returntheir intersection. Each element in the output result must be unique . We can regardless of the order of the output results .

    Example 1:

    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    

    Example 2:

    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]
    解释:[4,9] 也是可通过的
    
Idea:
  • First put an array into HashSet, because set has a self-service deduplication function. You can take advantage of this function, and then traverse the second Array, if the elements in the second array appear in HashSet, they can be added to another HashSet. Then convert the newHashSet into an array.
  • HashSetThere is a self-service deduplication function.
class Solution {
    
    
    public int[] intersection(int[] nums1, int[] nums2) {
    
    
        //两个数组的交集
        Set<Integer> array = new HashSet<Integer>();
        Set<Integer> set = new HashSet<Integer>();

        //先将一个加入到hashset当中
        for(int x : nums1){
    
    
                set.add(x);
        }
        //判断另外一个
        for(int x : nums2){
    
    
            if(set.contains(x)){
    
    
                array.add(x);
            }
        }
        //转换为数组
        int n = array.size();
        int ans[] = new int[n];
        int index = 0;
        for(int x : array){
    
    
            ans[index++] = x;
        }
        return ans;
        // return array.stream().mapToInt(Integer::intValue).toArray();
    }
}

happy number

topic:

Click on the question link

Write an algorithm to determine whether a number n is a happy number.

``pleasure number'' fixed value:

  • For a positive integer, each time the number is replaced by the sum of the squares of its digits at each position.
  • Then repeat this process until the number becomes 1, or it may be infinite loop but it never reaches 1.
  • If the result of this process is 1, then this number is the happy number.

as a result n is pleasant number return times true ;not, Turn around false.

Example 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

Example 2:

输入:n = 2
输出:false
Idea:
  • First of all, if you perform manual derivation by yourself, you will find that the happy number will not always increase, and there will only be two possibilities:
    • Continuously cycle through numbers that have appeared before
    • The sum of the digits is 1
  • Write a function to find the sum of digits, and then use a hash table or fast and slow pointers to find it.
    • If 1 appears, returntrue, if loop returnsfalse
class Solution {
    
    
    public int nextNum(int n){
    
    
        int next = 0;
        //求取n各个位置上的数,然后求平方
        while(n > 0){
    
    
            int temp = n % 10;
            next += temp*temp;
            n /= 10;
        }
        return next;
    }

    public boolean isHappy(int n) {
    
    
        //注意,n要么一直被循环,要么就是为1,不会一直变大
        //方法一:Hash表
        //每次替换成数字的平方和
    //    HashSet<Integer> set = new HashSet<Integer>();
    //    while(true){
    
    
    //        if(n == 1) return true;
    //        if(!set.contains(n)){
    
    
    //            set.add(n);
    //        }
    //        else return false;
    //        n = nextNum(n);
    //    }
       //方法二:快慢指针
       int slow = n;
       int fast = n;
       while(true){
    
    
           slow = nextNum(slow);
           fast = nextNum(fast);
           fast = nextNum(fast);
           if(slow == 1 || fast == 1) return true;
           if(slow == fast) return false;
       }
    //    return true;
    }
}

ransom letter

topic:

Click on the question link

Give you two strings: ransomNote and magazine, determine whether ransomNote can be represented by < a consists of the characters inside i=4>. magazine

Whether it is possible, return true; no return false.

magazineEach character in can be used only once in ransomNote.

Example 1:

输入:ransomNote = "a", magazine = "b"
输出:false

Example 2:

输入:ransomNote = "aa", magazine = "ab"
输出:false

Example 3:

输入:ransomNote = "aa", magazine = "aab"
输出:true
Idea:
  • Since the string only contains lowercase characters, the implementation of the table can be simulated directly through the int arrayhash
  • The specific implementation is to first convert the string type into a character array type, and then traverse two arrays. One array counts the number of occurrences of each character from the forward direction, and the other array The array counts the number of occurrences of characters from reverse. Finally, traverse the array again to determine whether a symbol less than 0 appears in the array element. If it does, it means that the conditions are not met.
class Solution {
    
    
    public boolean canConstruct(String ransomNote, String magazine) {
    
    
        int nums[] = new int[26];
        char mag[] = magazine.toCharArray();
        char ransom[] = ransomNote.toCharArray();

        for(char x : mag){
    
    
            nums[x-'a']++;
        }
        for(char x : ransom){
    
    
            nums[x-'a']--;
            if(nums[x-'a'] < 0) return false;
        }
        return true;
    }
}

sum of two numbers

topic:

Click on the question link

Given an integer arraynums and an integer target valuetarget, please find The two integers whose sum is the target valuetarget and return their array subscripts.

You can assume that each input will correspond to only one answer. However, the same element in the array cannot appear repeatedly in the answer.

You can return answers in any order.

Example 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

Example 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

Example 3:

输入:nums = [3,3], target = 6
输出:[0,1]
Idea:
  • Use the hash table, sacrifice space for time, traverse the array, if the element appears for the first time, put it into the hash table, and storetarget-该元素的值
  • If it does not appear for the first time, determine whether the number appears in the hash table. If it appears, it means that the conditions are met and return.
class Solution {
    
    
    public int[] twoSum(int[] nums, int target) {
    
    
        //hash表的使用刷题
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        int ans[] = new int[2];
        for(int i = 0; i < nums.length; i++){
    
    
            if(map.containsKey(nums[i])){
    
    
                return new int[]{
    
    i,map.get(nums[i])};
            }
            else{
    
    
                map.put(target-nums[i], i);
            }
        }
        return new int[0];
    }
}

sum of three numbers

topic:

Click on the question link

Give you an integer arraynums and determine whether there is a triplet[nums[i], nums[j], nums[k]] that satisfiesi != j, i != k and j != k, and also satisfies nums[i] + nums[j] + nums[k] == 0. Please

You return all non-duplicate triples whose sum is 0.

**Note:** Answers cannot contain duplicate triples.

Example 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

Example 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

Example 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0
Idea:
  • Sorting + double pointers
  • First sort the array, fix a number after sortingnums[i], and then use the left and right pointers to point to the two ends behind nums[i], the numbers are nums[j]Sumnums[k], calculate the sum of three numbers and judge whether it is 0, if it is satisfied, add it to the result
  • (Key point) If you ensure that the elements added to the result array are not repeated:
    • If nums[i] == nums[i−1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
    • If nums[j] == nums[j-1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
    • Don’t you want to find k? Because as long as one k is satisfied, it will be added to the result, and k-- will not continue to be traversed later .
  • Note the definition of a variable-length two-dimensional array
class Solution {
    
    
    public List<List<Integer>> threeSum(int[] nums) {
    
    
        // 排序+双指针
        Arrays.sort(nums);
        int n = nums.length;
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        for(int i = 0; i <  n; i++){
    
    

            //保证i不重复
            if( i > 0 && nums[i] == nums[i-1]) continue;

            //目标值
            int target = nums[i];

            //遍历j
            for(int j = i+1; j < n; j++){
    
    
                //保证j不重复
                if( j > i+1 && nums[j] == nums[j-1]) continue;
                
                //遍历k
                int k = n - 1;
                while(k > j && nums[k] + nums[j] + target > 0) k--;

                if(k == j) break;       //没有找到

                if(nums[k] + nums[j] + target == 0){
    
    
                    List<Integer> sum = new ArrayList<Integer>();
                    sum.add(nums[i]);
                    sum.add(nums[j]);
                    sum.add(nums[k]);
                    ans.add(sum);
                }
            }
        }
        return ans;
    }
}

sum of four numbers

topic:

Click on the question link

Give you an array of n integers nums , and a target value target . Please find and return the four-tuple that satisfies all the following conditions and does not repeat (if two four-tuples If the tuple elements correspond one to one, the two quadruples are considered to be repeated):[nums[a], nums[b], nums[c], nums[d]]

  • 0 <= a, b, c, d < n
  • a, b, c sum d mutuality
  • nums[a] + nums[b] + nums[c] + nums[d] == target

You can return answers in any order.

Example 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

Example 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
Idea:
  • Sorting + double pointers, the idea is similar to the sum of three numbers.

  • First sort the array. After sorting, fix two numbers nums[i] and nums[j], and then use the left and right pointers to point to the two ends at the end. The numbers are respectively For nums[left] and nums[right], calculate the sum of the four numbers to determine whether it is 0, and if it is, add it to the result

  • (Key point) If you ensure that the elements added to the result array are not repeated:

    • If nums[i] == nums[i−1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
    • If nums[j] == nums[j-1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
    • Ifnums[left] == nums[left+1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
    • Ifnums[right] == nums[right-1], it means that the number is repeated, which will lead to repeated results, so it should be skipped
  • Pruning:

    • The smallest four numbers are greater than target and exit the loop
    • If the current number and the last three numbers are less than the target, jump out of the current loop.
class Solution {
    
    
    public List<List<Integer>> fourSum(int[] nums, int target) {
    
    
        //四数之和
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        int n = nums.length;

        //遍历第一重i
        for(int i = 0; i < n-3; i++){
    
    
            //排除重复项
            if(i > 0 && nums[i] == nums[i-1]) continue;

            //剪枝, 最小的四个数大于target退出循环
            if((long)nums[i] + nums[i+1] + nums[i+2] + nums[i + 3] > target) break;
            //剪枝,当前的数,与最后面的三个数小于target,跳出当前循环
            if((long)nums[i] + nums[n - 3] + nums[n - 2] + nums[n -1] < target) continue;

            //遍历第二重循环
            for(int j = i + 1; j < n-2; j++){
    
    
                //排除重复项
                if(j > i+1 && nums[j] == nums[j-1]) continue;

                //剪枝, 最小的四个数大于target退出循环
                if((long)nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) break;
                //剪枝,当前的数,与最后面的两个数小于target,跳出当前循环
                if((long)nums[i] + nums[j] + nums[n - 2] + nums[n -1] < target) continue;

                //双指针遍历第三个和第四个数
                int left = j + 1, right = n - 1;
                while(left < right){
    
    
                    long sum = (long)(nums[i] + nums[j] + nums[left] + nums[right]);
                    //等于目标值,加入ans中
                    if( sum == target){
    
    
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(nums[left]);
                        list.add(nums[right]);
                        ans.add(list);

                        //排除重复项
                        while(left < right && nums[left] == nums[left+1]) left++;
                        while(left < right && nums[right] == nums[right-1]) right--;
                        left++;
                        right--;
                    }
                    //继续往下找
                    else if(sum < target) left++;
                    else right--;
                }
            }
        }
        return ans;
    }
}

Guess you like

Origin blog.csdn.net/m0_46335449/article/details/134888517