【问题标题】:Left circular rotate an ArrayList then get index of max element左循环旋转一个 ArrayList 然后获取最大元素的索引
【发布时间】:2019-08-23 15:13:59
【问题描述】:

我需要根据第二个数组列表的每个元素左循环旋转一个数组列表,然后返回另一个列表,该列表具有旋转后的数组列表的最大元素索引。 (每次旋转都应该在原来的arraylist形成上进行)

例如我有这两个数组列表:rotatelist[1,2,3,4],rotate[1,2,3]

流程是:

rotatelist[1,2,3,4],rotate[1] -> [2,3,4,1] : max element index= 2

rotatelist[1,2,3,4],rotate[2] -> [3,4,1,2] : 最大元素索引= 1

rotatelist[1,2,3,4],rotate[3] -> [4,3,2,1] : 最大元素索引= 0

下面的代码可以正常工作,但是当一个测试用例的数组列表元素大小达到大约 100,000 时,总是会显示“由于超时而终止”错误,因为我在 HackerRank 上运行它

List<Integer> indices = new ArrayList<>(rotate.size());

for(int i=0;i<rotate.size();i++){
//rotate arraylist to the left
Collections.rotate(rotatelist,-rotate.get(i));

//get and insert max element index to array 
indices.add(rotatelist.indexOf(Collections.max(rotatelist)));

//rotate back to previous positions
Collections.rotate(rotatelist,rotate.get(i));           
}
return indices;

那么还有其他方法可以优化这段代码的性能吗?

在性能方面,使用传统的 for 循环是否比使用 Collections.rotate() 更好?

【问题讨论】:

  • 你能不能 a) 将所有旋转组合成一个旋转,b) 计算最大元素的索引 once 然后做一些简单的算术来生成另一个要返回的集合元素?

标签: java arraylist circular-buffer


【解决方案1】:

首先,忘记实际旋转任何东西,而是考虑仅对其中一个元素(特别是最大的元素)发生什么变化。

我不想用勺子喂你代码。相反,请考虑以下想法:

找到最大元素的索引,命名为iMax

n旋转后最大元素的位置为(iMax - n + array.length) % array.length

如果n 可以小于零或大于array.length,则需要将其置于该范围内,因为对于正n,nn % array.length 的旋转给出相同的结果.

您应该能够围绕这些想法构建一些代码。

【讨论】:

    【解决方案2】:

    如果您需要在每次旋转后只返回最大元素的索引,那么您不需要实际旋转列表。您可以计算初始列表中最大元素的索引,然后使用一些数学来计算现有索引在旋转后将转换为哪个索引。

    【讨论】:

      【解决方案3】:

      也许你可以试试这个解决方案

      public static List<Integer> rotateLeft(int d, List<Integer> arr) {
      // Get head of the rotated array
      int head = -99;
          for(int i = 0; d >=0; i++){
              head = arr.get(i);
              if(i == arr.size()-1){
                  i = -1;
              }   
              d--;   
          }
          // get elements from head to the end of the original array
          List<Integer>sub = arr.subList(arr.lastIndexOf(head),arr.size());
      
          // get elements from begginning to head
          List<Integer>remainder = arr.subList(0,arr.lastIndexOf(head));
      
          // concat them 
          List<Integer>newl = new ArrayList<Integer>(sub);
          newl.addAll(remainder);
      
          return newl;
      }
      

      【讨论】:

        【解决方案4】:

        我尝试了您发布的 sn-p 代码,您可以从上面的代码中查看:

        package stackoverflow;
        
        import java.util.ArrayList;
        import java.util.Arrays;
        import java.util.Collections;
        import java.util.List;
        import java.util.stream.Collectors;
        
        public class Rotate {
        
            public static void main(String[] args) {
        
                int[] a = { 1, 2, 3, 4};  
                List<Integer> rotatelist = Arrays.stream(a).boxed().collect(Collectors.toList());
                int[] b = { 1, 2, 3};  
                List<Integer> rotate = Arrays.stream(b).boxed().collect(Collectors.toList());
                List<Integer> maxindexes = maxIndexes(rotate, rotatelist);
                System.out.println(maxindexes);
            }
        
            public static List<Integer> maxIndexes(List<Integer> rotate, List<Integer> rotatelist) {
                List<Integer> indices = new ArrayList<>(rotate.size());
        
                for(int i=0;i<rotate.size();i++){
                //rotate arraylist to the left
                Collections.rotate(rotatelist,-rotate.get(i));
        
                //added to print rotated arrays
                System.out.println(rotatelist);
        
                //get and insert max element index to array 
                indices.add(rotatelist.indexOf(Collections.max(rotatelist)));
        
                //rotate back to previous positions
                Collections.rotate(rotatelist,rotate.get(i));           
                }
                return indices;
            }
        
        }
        

        您可以查看我在方法中使用了指令System.out.println(rotatelist)来打印旋转后的数组,我得到了以下结果:

        rotatelist[1,2,3,4],rotate[1] -> [2,3,4,1] : max element index= 2

        rotatelist[1,2,3,4],rotate[2] -> [3,4,1,2] : 最大元素索引= 1

        rotatelist[1,2,3,4],rotate[3] -> [4,1,2,3] : 最大元素索引= 0 所以第三个数组是 [4, 1, 2, 3] (原始数组旋转了三个位置)而不是 [4、3、2、1]。

        您提到的超时问题的可能解决方案是复制原始数组: [1, 2, 3, 4] 现在将变为 [1, 2, 3, 4, 1, 2, 3, 4]。 现在您可以获得数组 [1, 2, 3, 4] 迭代新的重复数组的旋转:

        对于 rotate[0] = 1 旋转数组从重复数组的索引 1 开始 [1, 2, 3, 4, 1, 2, 3, 4] 和 index = 1 和 length = 4 -> [2, 3, 4, 1]

        对于 rotate[1] = 2,旋转数组从重复数组的索引 2 开始 [1, 2, 3, 4, 1, 2, 3, 4] 和 index = 2 和 length = 4 -> [3, 4, 1, 2]

        对于 rotate[2] = 3,旋转数组从重复数组的索引 2 开始 [1, 2, 3, 4, 1, 2, 3, 4] 和 index = 3 和 length = 4 -> [4, 1, 2, 3]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-14
          • 1970-01-01
          • 2016-10-20
          • 2020-07-31
          • 1970-01-01
          • 2013-08-11
          相关资源
          最近更新 更多