首页 > 其他分享 >LeetCode 2808 使循环数组所有元素相等的最少秒数

LeetCode 2808 使循环数组所有元素相等的最少秒数

时间:2024-01-30 13:24:32浏览次数:27  
标签:arr 秒数 nums int max 元素 2808 LeetCode size

题目描述

原题链接: 2808.使循环数组所有元素相等的最少秒数
image

解题思路

  • 每次变化可以选择变成前一个元素或后一个元素,包括 [0] 和 [n - 1] 的转化;
  • 换个角度思考,每秒最多可以有两个不同元素nums[i-1]和nums[i+1]变化成nums[i]元素;
  • 假设nums[i]元素只出现一次,想要将所有元素同化那么每秒只能同化两个,下一秒仍然只能从已同化区域的两端继续同化两个;
  • 如果nums[i]元素值出现两次,这两次中间的不同元素个数为x,那么想要将x个元素全部同化就需要"x / 2"秒;
  • 总结一下,每秒可以向两边同化2个不同元素,每个元素相邻两次出现的间距元素个数最大值除以2就是将数组全部同化的秒数;
  • 因为是循环数组,所以还要考虑首尾分段的这种特殊间距情况。

解题代码

  /**
   * 哈希表记录元素下标集合,计算间距最大值得到变化所需次数
   * 执行用时: 69 ms , 在所有 Java 提交中击败了 76.56% 的用户
   * 内存消耗: 79.25 MB , 在所有 Java 提交中击败了 45.31% 的用户
   */
  public int minimumSeconds(List<Integer> nums) {
      if (nums == null || nums.size() < 2) {
          return 0;
      }
      Map<Integer, List<Integer>> idxListMap = new HashMap<>();
      int n = nums.size();
      for (int i = 0; i < n; i++) {
          idxListMap.computeIfAbsent(nums.get(i), a -> new ArrayList<>()).add(i);
      }
      if (idxListMap.size() < 2) {
          // 原始数组元素全部相同
          return 0;
      }
      int ans = n;
      for (List<Integer> idxList : idxListMap.values()) {
          // 计算相同元素的下标间距最大值,初始化为循环数组需要考虑的首尾两个下标间距值
          int max = idxList.get(0) + n - idxList.get(idxList.size() - 1);
          for (int i = 1; i < idxList.size(); i++) {
              max = Math.max(idxList.get(i) - idxList.get(i - 1), max);
          }
          // 将数组变成当前元素值的次数为 max / 2
          ans = Math.min(ans, max / 2);
      }
      return ans;
  }

考虑到只需要计算相邻两次下标差值,没必要保存所有下标,可以进一步优化:

  /**
   * 
   * 执行用时: 47 ms , 在所有 Java 提交中击败了 93.75% 的用户
   * 内存消耗: 61.35 MB , 在所有 Java 提交中击败了 96.88% 的用户
   */
  public int minimumSeconds(List<Integer> nums) {
      if (nums == null || nums.size() < 2) {
          return 0;
      }
      /*
      * arr[0]: key第一次出现的下标
      * arr[1]: key值上一次出现的下标
      * arr[2]: key值相邻两次出现的中间元素个数+1的最大值
      */
      Map<Integer, int[]> map = new HashMap<>();
      int n = nums.size();
      for (int i = 0; i < n; i++) {
          int[] arr = map.computeIfAbsent(nums.get(i), k -> new int[3]);
          if (arr[2] == 0) {
              // 第一次出现
              arr[0] = arr[1] = i;
              arr[2] = -1;
          }
          else {
              arr[2] = Math.max(i - arr[1], arr[2]);
              arr[1] = i;
          }
      }
      if (map.size() < 2) {
          // 原始数组元素全部相同
          return 0;
      }
      int ans = n;
      for (int[] arr : map.values()) {
          // 循环数组情况下,元素第一次和最后一次出现的下标间距最大值可能由首尾两端形成
          int max = Math.max(arr[2], arr[0] + n - arr[1]);
          // 将数组变成当前元素值的次数为 max / 2
          ans = Math.min(ans, max / 2);
      }
      return ans;
  }

标签:arr,秒数,nums,int,max,元素,2808,LeetCode,size
From: https://www.cnblogs.com/coding-memory/p/17996888

相关文章

  • Leetcode刷题第五天-二分法-回溯
    215:第k个最大元素链接:215.数组中的第K个最大元素-力扣(LeetCode)em~~怎么说呢,快速选择,随机定一个目标值,开始找,左边比目标小,右边比目标大,左右同时不满足时,交换左右位置,直到左指针比右指针大,交换目标和右指针位置的值,此时右指针位置即时目标值的在排序好数组中的位置,如果k在右......
  • leetcode--98. 验证二叉搜索树(bfs)
    记录13:502024-1-28https://leetcode.cn/problems/validate-binary-search-tree/想岔方向了,想的太复杂了。首先思路是每个root节点必须大于左子树的最大节点,小于右边子树的最小节点。我的做法是记录下叶子节点,因为左边叶子节点的集合(vector)的最后一个节点为左子树的最大值......
  • Leetcode刷题第四天-双指针-二分法
    15:三个数之和链接:15.三数之和-力扣(LeetCode)em...双冲for循环,从头去遍历,0-(a+b)是否在列表中,最终timeout数组从小到大排序,设置三个指针,i从头遍历到lens-1,j从i+1开始,k从lens-1开始,sums==0,放入结果,大于0,k-1,小于0,j+1如果i和i+1比较,相同跳过的话,会丢结果,i和i-1相等跳过,因为i-1已......
  • [LeetCode] 2859. Sum of Values at Indices With K Set Bits
    Youaregivena0-indexedintegerarraynumsandanintegerk.Returnanintegerthatdenotesthesumofelementsinnumswhosecorrespondingindiceshaveexactlyksetbitsintheirbinaryrepresentation.Thesetbitsinanintegerarethe1'sprese......
  • 码农面试宝典之leetcode刷题手册
    今年的经济形势和行业状况可以说对求职者来说很不友好,你们是否曾因为面对编程面试题而感到迷茫?是否渴望提升自己的算法技能顺利跨入大厂?让我向你们推荐一项强大的利器——LeetCode刷题手册,它将成为你找到理想工作的秘密武器。LeetCode作为全球最受欢迎的在线编程平台之一,不仅拥有......
  • #yyds干货盘点# LeetCode程序员面试金典:和为 K 的子数组
    题目给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的子数组的个数。子数组是数组中元素的连续非空序列。 示例1:输入:nums=[1,1,1],k=2输出:2示例2:输入:nums=[1,2,3],k=3输出:2 代码实现publicclassSolution{publicintsubarr......
  • #yyds干货盘点# LeetCode程序员面试金典:左叶子之和
    题目给定二叉树的根节点root,返回所有左叶子之和。 示例1:输入:root=[3,9,20,null,null,15,7] 输出:24 解释:在这个二叉树中,有两个左叶子,分别是9和15,所以返回24示例2:输入:root=[1]输出:0代码实现classSolution{publicintsumOfLeftLeaves(Tr......
  • Leetcode刷题第三天-贪心-双指针
    738:单调递增链接:738.单调递增的数字-力扣(LeetCode)嘶~介个介个恶心心,从后往前遍历,前一个数比当前数大,前一个数-1,当前数变为9需要注意的是,保证每个9后面全是9100,第一轮遍历完时90T_T1classSolution:2defmonotoneIncreasingDigits(self,n:int)->int:3......
  • Leetcode刷题第二天-贪心
    655:非递减数列链接:665.非递减数列-力扣(LeetCode)直接找最大最小值进行替换不行,[1,5,4,6,7,8,9]最大最小值所处位置可能是非递减数列如果nums[i]>nums[i+1],当前这俩个数递减,修改谁,记录前一个数,比较前一个数和当前数的大小,前一个数大,小变大,后一个数大,大变小统计次数,出现两次......
  • templeetcode 22.括号生成
    leetcode22.括号生成第二十二题:括号生成1.回溯:publicList<String>generateParenthesis(intn){List<String>ans=newArrayList<String>();backtrack(ans,newStringBuilder(),0,0,n);returnans;}publicvoidbackt......