【问题标题】:Searching a value using for-loop and使用 for 循环搜索值和
【发布时间】:2018-12-06 19:52:01
【问题描述】:

问题是这样的:

给定一个非空整数数组,每个元素都出现两次,除了一个。找到那个。

输入:[4,1,2,1,2]
输出:4

我的代码是:

public static int singleNumber(int[] nums) {
     int answer = 0;
        for (int i =0; i<nums.length-1; i++) {
            for(int j = i+1; j<nums.length; j++) {
                if(nums[i] != nums[j]) {
                 answer = nums[i];      //this should be where I am wrong.
                }
            }
        }
        return answer;
    }

我知道输出是 4,然后现在它会变成 1。 我试图弄清楚如何在找到后不更改找到的值。

【问题讨论】:

  • 我会使用 HashBag(或使用 Map 实现这样的包),然后返回计数为 1 的所有对象的集合。
  • 输入数字有限制吗? (例如:它们在 1-10 等之间)
  • 我还没有学过哈希......所以这就是我现在正在做的事情。并且输入数字没有限制(抱歉之前没有具体说明)
  • 这是算法问题还是实现问题?

标签: java arrays loops for-loop unique


【解决方案1】:

这是一个使用 ArrayList.indexOf 和 A​​rrayList.lastIndexOf 的解决方案。如果它们相同,您就有答案了。

public static int singleNumber(int[] nums) {
    int answer = 0;
    //ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(nums));
    ArrayList al = new ArrayList();
    for (int i =0; i < nums.length; i++) {
        al.add(nums[i]);
    }

    for (int i =0; i < nums.length; i++) {
        int test = nums[i];
        if(al.indexOf(test) == al.lastIndexOf(test)){
            answer = nums[i];
        }
    }
    return answer;
 }

【讨论】:

    【解决方案2】:

    这是另一个使用 Java 8 中的Collectors.groupingBy 的解决方案:

    public static int singleNumber(int[] nums) {
        return Arrays.stream(nums).boxed()
                .collect(Collectors.groupingBy(a -> a, Collectors.counting()))
                .entrySet().stream().filter(e -> e.getValue() == 1).findFirst().get().getKey();
    }
    

    想法是:

    • 按出现次数分组
    • 然后找到只重复一次的那个

    注意我假设你的数组至少包含一个元素,否则你可以在搜索之前检查长度然后抛出这样的异常:

    public static int singleNumber(int[] nums) throws IllegalArgumentException{
        if(nums.length == 0){
            throw new IllegalArgumentException("empty array");
        }
        return Arrays.stream(nums).boxed()
                .collect(Collectors.groupingBy(a -> a, Collectors.counting()))
                .entrySet().stream().filter(e -> e.getValue() == 1).findFirst().get().getKey();
    }
    

    更深入一点,如果你想避免多个号码重复一次的情况,你可以使用:

    public static int singleNumber(int[] nums) throws IllegalArgumentException {
        if (nums.length == 0) {
            throw new IllegalArgumentException("empty array");
        }
        Map<Integer, Long> grouping = Arrays.stream(nums).boxed()
                .collect(Collectors.groupingBy(a -> a, Collectors.counting()));
        if (grouping.values().stream().filter(c -> c == 1).count() > 1) {
            throw new IllegalArgumentException("more than one element is repeated one time");
        }
    
        return grouping.entrySet().stream()
                .filter(e -> e.getValue() == 1).findFirst().get().getKey();
    }
    

    【讨论】:

      【解决方案3】:

      对于这个问题,我会对数字进行按位异或。相等的数字会相互抵消,只有一个整数是最终值。

      public static int singleNumber(int[] nums) {
           int answer = 0;
              for (int i =0; i<nums.length; i++) {
                 answer = answer ^ nums[i];
              }
              return answer;
       }
      

      【讨论】:

        【解决方案4】:

        对您方法的以下更改将为您提供预期的答案

        public static int singleNumber(int[] nums) {
        
            int temp = 0;
            int answer = 0;
        
            for (int i = 0; i < nums.length; i++) {
                boolean flag = true;
                temp = nums[i];
                for (int j = 0; j < nums.length; j++) {
                    if (temp == nums[j]) {
                        if (i != j) {// if a match found then the loop will terminate
                            flag = false;
                            break;
                        }
                    }
        
                }
                if (flag == true) {
                    answer = temp;
                }
            }
            return answer;
        }
        

        【讨论】:

          【解决方案5】:

          试试这个:

              int[] nums = new int[] {4,2,1,2,1};
                   int answer = 0;
                      for (int i =0; i<nums.length-1; i++) {
                          int times = 0;
                          int target = nums[i];
                          for(int j : nums) {
                              if(j == target) {
                                  times++;
                                  if(times == 2) {
                                      break;
                                  }
                              }
                          }
                          if(times == 1) {
                              answer = target;
                              break;
                          }
                      }
                      System.out.println(answer);
          

          你必须进入每个数字并计算数组中有多少个如果只有 1 你立即停止循环结束设置答案

          【讨论】:

          • 与其检查times==1,不如在times变为2时立即中断,然后你可以设置answer = target,如果它设法到达终点而不退出
          【解决方案6】:

          逻辑错误 - 您的内部循环会找到数组中不是唯一数字的每个数字。

          我会维护一个Set 来跟踪我遇到的数字。第一次遇到号码时,将其添加到Set。第二次遇到它时,将其从Set 中删除。完成数组检查后,您将拥有一个带有单个元素的 Set,这就是您的答案:

          public static int singleNumber(int[] nums) {
              Set<Integer> unique = new HashSet<>();
              for (int num : nums) {
                  // add returns true if num is indeed new to unique
                  if (!unique.add(num)) {
                      unique.remove(num);
                  }
              }
          
              return unique.iterator().next();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-22
            • 2013-08-28
            • 1970-01-01
            • 2021-04-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多