顺序遍历(最大值 · 第二最大值),排序 · 降序,快速选择,大根堆(最大堆,大顶堆)4 解法,求解《1464. 数组中两元素的最大乘积》

2022-08-27 00:29:11

顺序遍历(最大值 · 第二最大值),排序 · 降序,快速选择,大根堆(最大堆,大顶堆)4 解法,求解《1464. 数组中两元素的最大乘积》

例题

1464. 数组中两元素的最大乘积

给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)(nums[j]-1) 取得最大值。
请你计算并返回该式的最大值。
示例 1:
输入:nums = [3,4,5,2]
输出:12
解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)
(nums[2]-1) = (4-1)(5-1) = 34 = 12 。
示例 2:
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
示例 3:
输入:nums = [3,7]
输出:12

答案

顺序遍历 · 最大值 · 第二最大值

var maxProduct = function(nums) {
  const n = nums.length
  let max0 = max1 = 0
  for (let i = 0; i < n; i++) {
    if (max0 < nums[i]) {
      max1 = max0
      max0 = nums[i]
    } else if (max1 < nums[i]) {
      max1 = nums[i]
    }
  }
  return (max1 - 1) * (max0 - 1)
};
function maxProduct(nums: number[]): number {
  const n = nums.length
  let max0 = 0, max1 = 0
  for (let i = 0; i < n; i++) {
    if (max0 < nums[i]) {
      max1 = max0
      max0 = nums[i]
    } else if (max1 < nums[i]) {
      max1 = nums[i]
    }
  }
  return (max0 - 1) * (max1 - 1)
};

排序 · 降序

var maxProduct = function(nums) {
  return nums.sort((a, b) => b - a).slice(0, 2).reduce((p, v) => p * (v - 1), 1) 
};
function maxProduct(nums: number[]): number {
  return nums.sort((a, b) => b - a).slice(0, 2).reduce((p, v) => p * (v - 1), 1)
};
class Solution {
  function maxProduct($nums) {
    rsort($nums, SORT_NUMERIC);
    return ($nums[0] - 1) * ($nums[1] - 1);
  }
}
func maxProduct(nums []int) int {
  sort.Sort(sort.Reverse(sort.IntSlice(nums)))
  return (nums[0] - 1) * (nums[1] - 1)
}
func maxProduct(nums []int) int {
  sort.SliceStable(nums, func(i, j int) bool {
    return nums[i] > nums[j]
  })
  return (nums[0] - 1) * (nums[1] - 1)
}
class Solution {
  public int maxProduct(int[] nums) {
    Arrays.sort(nums);
    int n = nums.length;
    for (int i = 0; i < n >> 1; i++) {
      int t = nums[i];
      nums[i] = nums[n - 1 - i];
      nums[n - 1 - i] = t;
    }
    return (nums[0] - 1) * (nums[1] - 1);
  }
}
public class Solution {
  public int MaxProduct(int[] nums) {
    Array.Sort(nums, delegate(int a, int b) {
      return b - a;
    });
    return (nums[0] - 1) * (nums[1] - 1);
  }
}
static inline int cmp(const void *pa, const void *pb) {
  return *(int*)pb - *(int*)pa;
}
int maxProduct(int* nums, int numsSize){
  qsort(nums, numsSize, sizeof(int), cmp);
  return (nums[0] - 1) * (nums[1] - 1);
}
class Solution {
public:
  int maxProduct(vector<int>& nums) {
    sort(nums.begin(), nums.end(), greater<int>());
    return (nums[0] - 1) * (nums[1] - 1);
  }
};
class Solution:
  def maxProduct(self, nums: List[int]) -> int:
    nums.sort(reverse = True)
    return (nums[0] - 1) * (nums[1] - 1)
class Solution:
  def maxProduct(self, nums: List[int]) -> int:
    nums.sort(key = lambda v: -v)
    return (nums[0] - 1) * (nums[1] - 1)

快速选择

var maxProduct = function(nums) {
  quickSelect(nums, 0, nums.length - 1, 1, (a, b) => b - a)
  return (nums[0] - 1) * (nums[1] - 1)
};
const quickSelect = (nums, start, end, k, cb)=> {
  swap(nums, start, (start + end + (start + end >> 1)) / 3 | 0)
  const qivot = nums[start]
  let l = start, i = start + 1, r = end
  while (i <= r) {
    const d = cb(nums[i], qivot)
    if (d > 0) swap(nums, i, r--)
    else if (d < 0) swap(nums, i++, l++)
    else i++
  }
  if (l === k) return nums[l]
  return l < k ? quickSelect(nums, l + 1, end, k, cb) : quickSelect(nums, start, l - 1, k, cb)
}
const swap = (nums, a, b) => {
  const t = nums[a]
  nums[a] = nums[b]
  nums[b] = t
}
class Solution {
public:
  int maxProduct(vector<int>& nums) {
    nth_element(nums.begin(), nums.begin() + 1, nums.end(), greater<int>());
    return (nums[0] - 1) * (nums[1] - 1);
  }
};
function maxProduct(nums: number[]): number {
  quickSelect(nums, 0, nums.length - 1, 1, (a, b) => b - a)
  return (nums[0] - 1) * (nums[1] - 1)
};
const quickSelect = (nums: number[], start: number, end: number, k: number, cb:(a: number, b: number) => number) => {
  swap(nums, start, (start + end + (start + end >> 1)) /3 | 0)
  const pivot = nums[start]
  let l = start, i = l + 1, r = end
  while (i <= r) {
    const d = cb(nums[i], pivot)
    if (d > 0) swap(nums, i, r--)
    else if (d < 0) swap(nums, i++, l++)
    else i++
  }
  if (l === k) return nums[l]
  return l < k ? quickSelect(nums, l + 1, end, k, cb) : quickSelect(nums, start, l - 1, k, cb) 
}
const swap = (nums: number[], start: number, end: number) => {
  const t = nums[start]
  nums[start] = nums[end]
  nums[end] = t
}

大根堆

var maxProduct = function(nums) { // 自己实现 PriorityQueue 
  const n = nums.length, q = new MyPriorityQueue([], (a, b) => b - a)
  for (let i = 0; i < n; i++) q.push(nums[i])
  return (q.pop() - 1) * (q.pop() - 1)
};
class MyPriorityQueue {
  constructor (ar = [], compare = (a, b) => a - b) {
    this.heap = []
    this.size = 0
    this.compare = compare
    while (ar.length) this.push(ar.pop())
  }
  swap (a, b) {
    const t = this.heap[a]
    this.heap[a] = this.heap[b]
    this.heap[b] = t
  }
  getLeftIndex(index) {
    return (index << 1) + 1
  }
  getRightIndex(index) {
    return (index << 1) + 2
  }
  getParentIndex(index) {
    return index - 1 >> 1
  }
  shiftDown(index) {
    const leftIndex = this.getLeftIndex(index)
    const rightIndex = this.getRightIndex(index)
    if (leftIndex < this.size && this.compare(this.heap[index], this.heap[leftIndex]) > 0) {
      this.swap(index, leftIndex)
      this.shiftDown(leftIndex)
    }
    if (rightIndex < this.size && this.compare(this.heap[index], this.heap[rightIndex]) > 0) {
      this.swap(index, rightIndex)
      this.shiftDown(rightIndex)
    }
  }
  shiftUp(index) {
    const parentIndex = this.getParentIndex(index)
    if (parentIndex >= 0 && this.compare(this.heap[parentIndex], this.heap[index]) > 0) {
      this.swap(parentIndex, index)
      this.shiftUp(parentIndex)
    }
  }
  push(v) {
    this.heap.push(v)
    this.shiftUp(this.size++)
  }
  top() {
    return this.heap[0]
  }
  pop() {
    if (this.size === 0) return null
    if (--this.size === 0) return this.heap.pop()
    const top = this.top()
    this.heap[0] = this.heap.pop()
    this.shiftDown(0)
    return top
  }
  isEmpty() {
    return this.size === 0
  }
}
var maxProduct = function(nums) { // 使用自带类
  const n = nums.length, q = new MaxPriorityQueue()
  for (let i = 0; i < n; i++) q.enqueue(nums[i])
  return (q.dequeue().element - 1) * (q.dequeue().element - 1)
};

顺序遍历,栈,用 reduce / array_reduce / stream().reduce / Aggregate / accumulate 累积完成 1 行解,3 解法求解《1598. 文件夹操作日志搜集器》,
顺序遍历,栈,2 解法求解《1598. 文件夹操作日志搜集器》,用 reduce / array_reduce / stream().reduce / Aggregate / accumulate 累积完成 1 行解
顺序遍历 + 拼接字符串,倒序遍历 + 顺序遍历 + 双指针,repeat / str_repeat / strings.Repeat / new string() / string / * 重复字符串,join / implode / accumulate 数组列表转字符串,2 解法求解《1592. 重新排列单词间的空格》
顺序遍历 + 拼接字符串,倒序遍历 + 顺序遍历 + 双指针,repeat / str_repeat / strings.Repeat / new string() / string / * 重复字符串,join / implode / accumulate 数组列表转字符串,2 解法求解《1592. 重新排列单词间的空格》
定长列表(数组),原地修改,2 解法求解《1582. 二进制矩阵中的特殊位置》
定长列表(数组),原地修改,Python 使用 zip 旋转矩阵,2 解法求解《1582. 二进制矩阵中的特殊位置》