zoukankan      html  css  js  c++  java
  • Lettcode刷题笔记(二)

    448. 找到所有数组中消失的数字

    给定一个范围在  1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

    找到所有在 [1, n] 范围之间没有出现在数组中的数字。

    您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

    示例:

    输入:
    [4,3,2,7,8,2,3,1]

    输出:
    [5,6]

    老实说,第一次做这题时没做出来,大概是太菜了的原因。按照官方题解,这题有两种解法,一种是用HashMap,一种是原地修改。

    方法一:

    我们假设数组大小为 N,它应该包含从 1 到 N 的数字。但是有些数字丢失了,我们要做的是记录我们在数组中遇到的数字。然后从 1⋯N 检查哈希表中没有出现的数字。我们用一个简单的例子来帮助理解。

    算法:

    我们用一个哈希表 hash 来记录我们在数组中遇到的数字。我们也可以用集合 set 来记录,因为我们并不关心数字出现的次数。
    然后遍历给定数组的元素,插入到哈希表中,即使哈希表中已经存在某元素,再次插入了也会覆盖
    现在我们知道了数组中存在那些数字,只需从 1⋯N 范围中找到缺失的数字。
    从 1 ⋯N 检查哈希表中是否存在,若不存在则添加到存放答案的数组中。

    class Solution {
        public List<Integer> findDisappearedNumbers(int[] nums) {
            
            // Hash table for keeping track of the numbers in the array
            // Note that we can also use a set here since we are not 
            // really concerned with the frequency of numbers.
            HashMap<Integer, Boolean> hashTable = new HashMap<Integer, Boolean>();
            
            // Add each of the numbers to the hash table
            for (int i = 0; i < nums.length; i++) {
                hashTable.put(nums[i], true);
            }
            
            // Response array that would contain the missing numbers
            List<Integer> result = new LinkedList<Integer>();
            
            // Iterate over the numbers from 1 to N and add all those
            // that don't appear in the hash table. 
            for (int i = 1; i <= nums.length; i++) {
                if (!hashTable.containsKey(i)) {
                    result.add(i);
                }
            }
            
            return result;
        }
    }

    我的代码如下:

    class Solution {
        public List<Integer> findDisappearedNumbers(int[] nums) {
             
        HashMap<Integer,Integer> hashtable=new HashMap<Integer,Integer>();
        for(int i=0;i<nums.length;i++){
            hashtable.put(nums[i],i);
        }
        
        List<Integer> list=new ArrayList<Integer>();
        for(int i=1;i<nums.length+1;i++){
            if(!hashtable.containsKey(i)){
                list.add(i);
            }
        }
          return list; 
        }
    }

    大体上差不多,我的Hash表的key-value 对应的是 数字----下标.官方的是 数字---Boolean。

    用HashMap的关键是要记录的是出现的数字。因为这题它给数组范围是[1,n] (n是数组大小)。所以我们才可以用遍历,去找出hash表中不包含的数字。另外要注意当给的是[1,1]时,输出要求是2。所以我们才有i<nums.length+1。

    hashmap的方法   .containsKey() ----是否含有key值;  .put()----放入key,value值。

    方法二:原地修改


    我们需要知道数组中存在的数字,由于数组的元素取值范围是 [1, N],所以我们可以不使用额外的空间去解决它。
    我们可以在输入数组本身以某种方式标记已访问过的数字,然后再找到缺失的数字。
    算法:

    遍历输入数组的每个元素一次。
    我们将把 |nums[i]|-1 索引位置的元素标记为负数。即 nums[|nums[i] |- 1] imes -1nums[∣nums[i]∣−1]×−1 。
    然后遍历数组,若当前数组元素 nums[i] 为负数,说明我们在数组中存在数字 i+1。

    可以看官方给的图片方法

    class Solution {
        public List<Integer> findDisappearedNumbers(int[] nums) {
            
            // Iterate over each of the elements in the original array
            for (int i = 0; i < nums.length; i++) {
                
                // Treat the value as the new index
                int newIndex = Math.abs(nums[i]) - 1;
                
                // Check the magnitude of value at this new index
                // If the magnitude is positive, make it negative 
                // thus indicating that the number nums[i] has 
                // appeared or has been visited.
                if (nums[newIndex] > 0) {
                    nums[newIndex] *= -1;
                }
            }
            
            // Response array that would contain the missing numbers
            List<Integer> result = new LinkedList<Integer>();
            
            // Iterate over the numbers from 1 to N and add all those
            // that have positive magnitude in the array
            for (int i = 1; i <= nums.length; i++) {
                
                if (nums[i - 1] > 0) {
                    result.add(i);
                }
            }
            
            return result;
        }
    }

    这是一个非常巧妙的方法。巧妙地利用了下标这一属性。

    442. 数组中重复的数据

    给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。

    找到所有出现两次的元素。

    你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?

    示例:

    输入:
    [4,3,2,7,8,2,3,1]

    输出:
    [2,3]

    class Solution {
        public List<Integer> findDuplicates(int[] nums) {
          
          HashMap<Integer,Boolean> doublenums =new HashMap<Integer,Boolean>();
    
          for(int i=0;i<nums.length;i++){
             
              //第二次放入值为Ture
              if(doublenums.containsKey(nums[i])){
                 doublenums.put(nums[i],true);
              }else{
                    //第一次放入值为False
                doublenums.put(nums[i],false);
              } 
                   
          }
      
    
          List<Integer> returns=new LinkedList<Integer>();
          //遍历hashmap
          for(Integer i:doublenums.keySet()){
              if(doublenums.get(i)==true){
                  returns.add(i);
              }
          }
    
           
           return returns; 
        }
    }

    这一题与448题比较相似,我的解法也是利用HashMap,由448得到的灵感。

    这次hash表地key--value是Integer--boolean。当第一次放入数字时,Boolean值为false。第二次放入数字时,Booelan值为True,然后再遍历hash表找到Boolean值。

    hashmap的方法   

    //遍历Hash的key值
    for
    (Integer i:doublenums.keySet()){
    //通过key值得到value值
    if(doublenums.get(i)==true){ returns.add(i); } }

    41. 缺失的第一个正数

    给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。

     

    示例 1:

    输入: [1,2,0]
    输出: 3
    示例 2:

    输入: [3,4,-1,1]
    输出: 2
    示例 3:

    输入: [7,8,9,11,12]
    输出: 1

     

     
    class Solution {
        public int firstMissingPositive(int[] nums) {
                 
    
              HashMap<Integer,Integer> hashtable=new HashMap<Integer,Integer>();
              if(nums.length==0){
                  return  1;
              }
    
              for(int i=0;i<nums.length;i++){
    
                  //把大于0的正整数放入hash表中
                  if(nums[i]>0)
                     hashtable.put(nums[i],i);                 
              }
    
              //找出所有未出现的正整数
              List<Integer> list=new ArrayList<>();
              for(int i=1;i<=nums.length+1;i++){
                 if(!hashtable.containsKey(i))
                    list.add(i);
              } 
                     
             
              int a=list.get(0); 
              return a;
        }
    }

    这题的解法也是由448得到的灵感。只要取大于的值放入hash表中就可以了。最后取到数组的第一位就是最小的正整数。

  • 相关阅读:
    win2008R2、win7不停闪屏、程序失去响应的解决办法
    “我要上春晚”刷票器
    Windows Phone 7的About模板——Your Last About Dialog
    该伙伴事务管理器已经禁止了它对远程/网络事务的支持
    安装配置apache+php+mysql小结
    [摘]CSS的优先级探讨
    利用domdrag实现flash滚动条功能
    WIN7下如何做好IE6,7的兼容性测试
    同级情况下CSS的优先级探讨
    [NHibernate] NHibernate对象关系映射工具了解
  • 原文地址:https://www.cnblogs.com/tzs123/p/13606361.html
Copyright © 2011-2022 走看看