优化 FOR 循环以将数组元素添加到集合中

huangapple go评论72阅读模式
英文:

Optimize FOR loop for adding array elements to set

问题

我有一个大小为N的数组ArAr[N])。我需要将Ar[N]分成大小为K的子数组,然后将它们添加到集合S中。
例如,如果Ar[5] = {1,2,3,4,5}K = 3,那么子数组将是{1,2,3},{2,3,4},{3,4,5}
现在我需要将这些子数组添加到集合中,并继续我的计算。

以下是我的代码:

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。
注意:集合应该只包含唯一的值。
希望我表达清楚。

英文:

I have an array Ar of size N(Ar[N]). I have to divide the Ar[N] into sub arrays of size K and then add them to a Set S.
For example if Ar[5] = {1,2,3,4,5} and K = 3
then,
Sub arrays will be {1,2,3},{2,3,4},{3,4,5}
Now I have to add these sub arrays to the Set and continue my computations.

Here is my code :

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

Is there any way that I can get rid of the nested for loop as in worst case N can be 1000000.
NOTE : The set should only contain unique values.
Hope I am clear.

答案1

得分: 0

维护一个从 i-k-1i 的窗口,遍历数组时对集合进行操作。你可以使用 HashMap 来统计值的频率,并在频率为零时将其移除。然后更新集合的最大值,这样你就可以得到每个子数组的集合的最大大小。

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();
  }
}
英文:

Maintain a window of i-k-1 to i of set when traversing the array. You can use HashMap to count the frequency of value and remove it when the frequency is zero. And update max value of set then you will get max set size of each subarray's set.

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

答案2

得分: 0

以下是翻译好的代码部分:

如果实际任务是在分成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
英文:

If actual task is to define the maximum size of a subset after dividing into K elements, it can be implemented this way:

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

Also, splitting of the input array by K elements into subsets may be implemented this way:

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

Test and output:

int[] arr = {1, 2, 2, 2, 1};
int k = 3;

Set&lt;Set&lt;Integer&gt;&gt; result = splitIntoSubsetsByK(arr, k);
result.forEach(System.out::println);

System.out.println(findMaxSize(arr, k));

[1, 2]
[2]
2

答案3

得分: 0

替代方案。尝试使用在以下链接中描述的 "subList()" 方法:https://stackoverflow.com/questions/12099721/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);
    }

    // 查看 mainList:
    System.out.println(mainList); // 输出: [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);
    }

    // 查看所有子列表:
    System.out.println(listOfLists); // 输出: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
}

希望这对你有所帮助。

英文:

Alternative solution. Try to use "subList()" described in: https://stackoverflow.com/questions/12099721/how-to-use-sublist

See example below:

public static void main(String[] args) {
    int startNumber = 1;
    int endNumber = 5;
    List&lt;Integer&gt; mainList = new ArrayList&lt;&gt;();
    for (int i = startNumber; i &lt;= 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&lt;List&lt;Integer&gt;&gt; listOfLists = new ArrayList&lt;&gt;();
    for (int i = 0; i &lt;= loopStopPoint; i++) {
        List&lt;Integer&gt; 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]]
}

huangapple
  • 本文由 发表于 2020年8月9日 13:02:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63322637.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定