LeeCode 90双周赛复盘

T1: 差值数组不同的字符串

思路:数组遍历

  • 若前两个字符串差值数组不同,则只需要继续计算第三个字符串的差值数组即可得到答案
  • 若前两个字符串差值数组相同,则依次遍历后续字符串,直至找到不同的差值数组
public String oddString(String[] words) {
  int length = words[0].length();
  int[] difference1 = new int[length - 1];
  int[] difference2 = new int[length - 1];
  char[] chArr1 = words[0].toCharArray();
  char[] chArr2 = words[1].toCharArray();

  for (int i = 0; i < length - 1; i++) {
    difference1[i] = chArr1[i + 1] - chArr1[i];
    difference2[i] = chArr2[i + 1] - chArr2[i];
  }

  // 前两个字符串的差值数组相同
  if (isSame(difference1, difference2)) {
    for (int i = 2; i < words.length; i++) {
      char[] chArr = words[i].toCharArray();
      for (int j = 0; j < length - 1; j++) {
        difference2[j] = chArr[j + 1] - chArr[j]; 
      }

      if (!isSame(difference1, difference2)) {
        return words[i];
      }
    }
  }
  
  // 前两个字符串的差值数组不同
  else {
    char[] chArr = words[2].toCharArray();
    int[] difference3 = new int[length - 1];
    for (int i = 0; i < length - 1; i++) {
      difference3[i] = chArr[i + 1] - chArr[i];
    }

    if (isSame(difference1, difference3)) {
      return words[1];
    }
    else {
      return words[0];
    }
  }

  return null;
}

/**
 * 辅助函数, 判断两个差值数组是否相同
 * @param arr1
 * @param arr2
 * @return
 */
public boolean isSame(int[] arr1, int[] arr2) {
  for (int i = 0; i < arr1.length; i++) {
    if (arr1[i] != arr2[i]) {
      return false;
    }
  }

  return true;
}

T2: 距离字典两次编辑以内的单词

思路:数组遍历

public List<String> twoEditWords(String[] queries, String[] dictionary) {
  List<String> res = new ArrayList<>();
  for (String query : queries) {
    if (isSatisfy(query, dictionary)) {
      res.add(query);
    }
  }

  return res;
}


/**
 * 辅助函数, 判断单词是否满足两次以内
 * @param s
 * @param dictionary
 * @return
 */
public boolean isSatisfy(String s, String[] dictionary) {
  for (String dict : dictionary) {
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) != dict.charAt(i)) {
        count += 1;
      }

      if (count > 2) {
        break;
      }
    }

    if (count <= 2) {
      return true;
    }
  }

  return false;
}

T3: 摧毁一系列目标

思路:数组遍历 + 哈希

这道题的核心是找到数组元素对 space 取模后结果相等的最大个数,然后返回对应的元素最小值。

public int destroyTargets(int[] nums, int space) {
  /**
   * key: num 对 space 取模后的值
   * int[0]: 表示对 space 取模后值为 key 的数量
   * int[1]: 表示对 space 取模后值为 key 的最小 num
   */
  Map<Integer, int[]> map = new HashMap<>();

  for (int num : nums) {
    int temp = num % space;
    if (!map.containsKey(temp)) {
      map.put(temp, new int[]{1, num});
    }
    else {
      int[] arr = map.get(temp);
      arr[0] += 1;
      arr[1] = Math.min(arr[1], num);
      map.put(temp, arr);
    }
  }

  int maxCount = Integer.MIN_VALUE;
  int res= 0;
  for (Map.Entry<Integer, int[]> entry : map.entrySet()) {
    int[] arr = entry.getValue();
    if (maxCount < arr[0]) {
      res = arr[1];
      maxCount = arr[0];
    }
    else if (maxCount == arr[0]) {
      res = Math.min(res, arr[1]);
    }
  }

  return res;
}

T4: 下一个更大元素IV

思路:单调栈 + 小顶堆

  • 使用单调栈寻找元素右边第一个更大的元素
  • 若找到右边第一个更大的元素,则将该值从栈内弹出,加入小顶堆
  • 若当前元素大于堆顶的值,则说明当前元素为堆顶元素的第二个更大的元素
public int[] secondGreaterElement(int[] nums) {
  int n = nums.length;

  int[] ans = new int[n];
  Arrays.fill(ans, -1);

  Stack<Integer> stack = new Stack<>();
  Queue<Integer> queue = new PriorityQueue<>((o1, o2) -> {
    return nums[o1] - nums[o2];
  });

  for (int i = 0; i < n; ++i) {
    while (!queue.isEmpty() && nums[queue.peek()] < nums[i]) {
      ans[queue.peek()] = nums[i];
      queue.poll();
    }

    while (!stack.isEmpty() && nums[stack.peek()] < nums[i]) {
      queue.offer(stack.pop());
    }

    stack.push(i);
  }

  return ans;
}

总结

  1. 第三题耗时较长,一开始没有用哈希来存,直接开辟了 space 长度的二维数组,导致内存不足,需要对数据大小更敏感一些。
  2. 第四题限定时间内没有完成,能想到是用单调栈来找第一个更大的元素,但如何去找到第二个更大的元素未能完成。
posted @ 2022-10-30 15:34  ylyzty  阅读(18)  评论(0编辑  收藏  举报