【问题标题】:Optimize FOR loop for adding array elements to set优化 FOR 循环以添加数组元素进行设置
【发布时间】:2020-08-09 05:02:05
【问题描述】:

我有一个大小为 N(Ar[N]) 的数组 Ar。我必须将 Ar[N] 划分为大小为 K 的子数组,然后将它们添加到 Set S 中。 例如,如果 Ar[5] = {1,2,3,4,5}K = 3 然后, 子数组将是{1,2,3},{2,3,4},{3,4,5} 现在我必须将这些子数组添加到 Set 并继续我的计算。

这是我的代码:

int max = 0;
for(int j=0;j<=N-k;j++){
            Set<Integer> set = new HashSet<>();
            for(int l=j;l<j+K;l++){
                set.add(Ar[l]);
            }
if(set.size >= max) max = set.size;
        }
System.out.println(max);

有什么方法可以摆脱嵌套的 for 循环,因为在最坏的情况下 N 可以是 1000000。
注意:该集合应该只包含唯一值。 希望我清楚。

【问题讨论】:

  • 鉴于您所说的问题,实际上没有一种方法可以提高效率。您所做的任何事情最终都需要完成 O(NK) 工作。
  • 你能给出完整的问题陈述吗?因为在这个层面上我同意路易斯的观点
  • 你能展示一下你是如何使用子数组的吗?也许可以改变程序,所以没有必要完全构建这个集合
  • 嗨@Joni,我计算了集合的最大大小。我将它添加到我的代码中。请看一下。
  • 但在我们的代码中,我看到的是一组整数而不是一组整数数组。我错过了什么?

标签: java arrays for-loop set


【解决方案1】:

在遍历数组时维护一个i-k-1i的窗口。您可以使用HashMap 来统计 value 的频率,并在频率为零时将其删除。并更新集合的最大值,然后您将获得每个子数组集合的最大集合大小。

int[] arr = {1,2,1,4,1};
int k = 3;
int max = 0;
Map<Integer, Integer> map = new HashMap<>();
Set<Integer> set = new HashSet<>();
for (int i = 0; i < arr.length; i++) {
  set.add(arr[i]);
  map.merge(arr[i], 1, Integer::sum);
  if(i >= k) {
    map.merge(arr[i-k], -1, Integer::sum);
    if(map.get(arr[i-k]) == 0) {
      set.remove(arr[i-k]);
    }
  }
  if(set.size() >= max) {
    max = set.size();
  }
}

【讨论】:

  • 你检查过这个解决方案了吗?
【解决方案2】:

替代解决方案。尝试使用“subList()”中描述的:How to use subList()

请看下面的例子:

public static void main(String[] args) {
    int startNumber = 1;
    int endNumber = 5;
    List<Integer> mainList = new ArrayList<>();
    for (int i = startNumber; i <= endNumber; i++) {
        mainList.add(i);
    }

    // See mainList:
    System.out.println(mainList); // output: [1, 2, 3, 4, 5]

    int sizeOfEachSubList = 3;
    int loopStopPoint = mainList.size() - sizeOfEachSubList;
    List<List<Integer>> listOfLists = new ArrayList<>();
    for (int i = 0; i <= loopStopPoint; i++) {
        List<Integer> subList = mainList.subList(i, sizeOfEachSubList + i);
        listOfLists.add(subList);
    }

    //See all lists:
    System.out.println(listOfLists); // output: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
}

【讨论】:

    【解决方案3】:

    如果实际任务是定义一个子集划分为K个元素后的最大尺寸,可以这样实现:

    public static long findMaxSize(int[] arr, int k) {
        return IntStream.rangeClosed(0, arr.length - k)
                        .mapToLong(i -> 
                            Arrays.stream(Arrays.copyOfRange(arr, i, i + k))
                                  .distinct().count())
                        .max().getAsLong();
    }
    

    此外,将输入数组按 K 个元素拆分为 子集 可以这样实现:

    public static Set<Set<Integer>> splitIntoSubsetsByK(int[] arr, int k) {
        return IntStream.rangeClosed(0, arr.length - k)
                        .mapToObj(i -> Arrays.stream(Arrays.copyOfRange(arr, i, i + k))
                            .boxed().collect(Collectors.toSet()))
                        .collect(Collectors.toCollection(LinkedHashSet::new));
        }
    

    测试和输出:

    int[] arr = {1, 2, 2, 2, 1};
    int k = 3;
    
    Set<Set<Integer>> result = splitIntoSubsetsByK(arr, k);
    result.forEach(System.out::println);
    
    System.out.println(findMaxSize(arr, k));
    
    [1, 2]
    [2]
    2
    

    【讨论】:

      猜你喜欢
      • 2020-03-20
      • 2018-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-02
      • 2019-11-05
      • 1970-01-01
      • 2016-09-18
      相关资源
      最近更新 更多