leetcode之哈希表刷题总结1

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode之哈希表刷题总结1相关的知识,希望对你有一定的参考价值。

leetcode之哈希表刷题总结1

1-两数之和
题目链接:题目链接这里!!!

思路:本题不难,但也没有想象的那么简单,需要使用hash表,把时间复杂度控制到O(n)内。不用hash表直接暴力就是O(n^2)的复杂度,会超时。

class Solution 
    public int[] twoSum(int[] nums, int target) 
        Map<Integer,Integer> map  = new HashMap<>() ;
        int [] res = new int [2] ;
       
        for(int i=0; i<nums.length; i++)
            map.put(target-nums[i],i) ;
        
        for(int i=0; i<nums.length; i++)
           if(map.containsKey(nums[i]))
               res[0] = i ;
               res[1] = map.get(nums[i]) ;
               if(res[0]!=res[1])
               return res ;
               
           
        
        return res ;

    


2-有效的数独
题目链接:题目链接戳这里!!!

思路:三个数组标记,分别标记每个元素再对应的行,列,3*3方格的出现次数。

class Solution 
    public boolean isValidSudoku(char[][] board) 
        int [][] row = new int [9][9] ;
        int [][] column = new int [9][9] ;
        int [][][] vis = new int [3][3][9] ;
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
                if(board[i][j] != '.')
                    int idx = board[i][j] - '0' - 1 ;
                    row[i][idx] ++ ;
                    column[j][idx] ++ ;
                    vis[i/3][j/3][idx] ++ ;
                    if(row[i][idx]>1 || column[j][idx]>1 || vis[i/3][j/3][idx]>1)
                        return false ;
                    
                
            
        
        return true ;
    

3-矩阵置零
题目链接:题目链接戳这里!!!

思路1:使用行标记数组和列标记数组,记录出现0的行列,再次遍历遇到该行或者该列,修改数组元素为0即可,不过题目要求空间复杂度为O(1),即不开辟额外的存储空间,我们需要思路2。

class Solution 
    public void setZeroes(int[][] matrix) 
        int [] row = new int [matrix.length] ;
        int [] column = new int [matrix[0].length] ;
        for(int i=0; i<matrix.length; i++)
            for(int j=0; j<matrix[0].length; j++)
                if(matrix[i][j] == 0)
                    row[i] = 1 ;
                    column[j] = 1 ;
                
            
        
        for(int i=0; i<matrix.length; i++)
            for(int j=0; j<matrix[0].length; j++)
                if(row[i]==1 || column[j]==1)
                    matrix[i][j] = 0 ;
                
            
        
    


思路2:我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 0。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 0。

在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理第一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。

class Solution 
    public void setZeroes(int[][] matrix) 
        boolean row = false,  column = false ;
        for(int i=0; i<matrix.length; i++)
            if(matrix[i][0]==0)
                column = true ;
            
        
        for(int j=0; j<matrix[0].length; j++)
            if(matrix[0][j]==0)
                row = true ;
            
        

        for(int i=1; i<matrix.length; i++)
            for(int j=1; j<matrix[0].length; j++)
                if(matrix[i][j] == 0)
                    matrix[i][0] = 0;
                    matrix[0][j] = 0 ;
                
            
        
        for(int i=1; i<matrix.length; i++)
            for(int j=1; j<matrix[0].length; j++)
                if(matrix[i][0]==0 || matrix[0][j]==0)
                    matrix[i][j] = 0  ;
                
            
        
        if(row)
            for(int j=0; j<matrix[0].length; j++)
                matrix[0][j] = 0 ;
            
        
        if(column)
            for(int i=0; i<matrix.length; i++)
                matrix[i][0] = 0 ;
            
        

    


4-存在重复元素
题目链接:题目链接戳这里!!!

思路1:hashmap存储每个元素,如果第一次出现,则存储,否则返回true

class Solution 
    public boolean containsDuplicate(int[] nums) 
        Map<Integer, Integer> map = new HashMap<>() ;
        for(int i=0; i<nums.length; i++)
            if(map.get(nums[i])==null)
                map.put(nums[i],1) ;
            else
                return true  ;
            
        
        return false ;
    


思路2:用set集合的去重机制,比较去重后的集合大小和原数组大小是否一致。

class Solution 
    public boolean containsDuplicate(int[] nums) 
        Set<Integer> set = new HashSet<>() ;
        for(int i=0; i<nums.length; i++)
            set.add(nums[i]) ;
        
        return (set.size()==nums.length) ? false : true  ;
    


思路3:先排序,再比较有没有连个相邻元素相等。

class Solution 
    public boolean containsDuplicate(int[] nums) 
        Arrays.sort(nums) ;
        for(int i=1; i<nums.length; i++)
            if(nums[i-1]==nums[i])
                return true ;
            
        
      return false ;      
    


5-求众数
题目链接:题目链接戳这里!!!

思路1:使用hashmap存储每个元素出现的次数,只要大于n/3次的,存到set集合。

class Solution 
    public List<Integer> majorityElement(int[] nums) 
        int n = nums.length ;
        Set<Integer> set = new TreeSet<>() ;
    
        Map<Integer,Integer> map = new HashMap<>() ;
        for(int i=0; i<nums.length; i++)
            map.put(nums[i],map.getOrDefault(nums[i],0)+1) ;
        
        for(int i=0; i<nums.length; i++)
            if(map.get(nums[i]) > n/3)
                set.add(nums[i]) ;
            
        
        return new ArrayList<>(set) ;
    


思路2:hashmap存储每个元素的出现次数,如果大于n/3,且该元素不在list集合中,则存入。

class Solution 
    public List<Integer> majorityElement(int[] nums) 
        int n = nums.length ;
        List<Integer> list = new ArrayList<>() ;
    
        Map<Integer,Integer> map = new HashMap<>() ;
        for(int i=0; i<nums.length; i++)
            map.put(nums[i],map.getOrDefault(nums[i],0)+1) ;
        
        for(int i=0; i<nums.length; i++)
            if(map.get(nums[i]) > n/3 && !list.contains(nums[i]))
                list.add(nums[i]) ;
            
        
        return list;
    


6-回文排列
题目链接:题目链接戳这里!!!

思路:用set集合存储元素,如果第一次出现就存储,否则就删除,如果最后存在大于等于2个不一样的元素,则不是回文排列,反之是回文排列。

class Solution 
    public boolean canPermutePalindrome(String s) 
      Set<Character> set = new HashSet<>() ;
      for(int i=0; i<s.length(); i++)
          if(set.contains(s.charAt(i)))
              set.remove(s.charAt(i)) ;
          else
              set.add(s.charAt(i)) ;
          
      
      return set.size()<=1 ;
    


7-递增子序列
题目链接:题目链接戳这里!!!

思路:递归+回溯
其实就是递归找出所有的子集,防止出现重复的情况,
如果当前元素大于等于上一个选择的元素,则选择,也可以不选择。
如果当前的元素不等于上一个选择元素,才考虑可以不选。

即大于的时候,可以选,也可以不选,等于的时候必须选,不等于的时候可以不选。

class Solution 
    List<Integer> temp = new ArrayList<>() ;
    List<List<Integer>> ans = new ArrayList<>() ;
    public List<List<Integer>> findSubsequences(int[] nums) 
        //递归+回溯
        dfs(nums,0,Integer.MIN_VALUE) ;
        return ans ;
    
    public void dfs(int [] nums, int cur, int pre)
        if(cur==nums.length)
            if(temp.size()>=2)
                ans.add(new ArrayList<>(temp)) ;
            
            return ;
        
        if(nums[cur] >= pre)
            temp.add(nums[cur]) ;
            dfs(nums,cur+1,nums[cur]) ;
            temp.remove(temp.size()-1) ;
        
        if(nums[cur] != pre)
            dfs(nums,cur+1以上是关于leetcode之哈希表刷题总结1的主要内容,如果未能解决你的问题,请参考以下文章

leetcode之滑动窗口刷题总结1

链表刷题集合

链表刷题集合

链表刷题集合

leetcode之分治刷题总结1

leetcode之模拟刷题总结1