leetcode 229. Majority Element II | 229. 求众数 II(找出现次数超过n/k的元素)
題目
https://leetcode.com/problems/majority-element-ii/
題解
思路來源于左程云《程序員代碼面試指南》
問題描述
原問題:給定一個整型數組 arr,打印其中出現次數大于一半的數。
進階問題:給定一個整型數組 arr,再給定一個整數 K,打印所有出現次數大于 N/K 的數。
要求
原問題要求時間復雜度為 O(N),額外空間復雜度為 O(1)。
進階問題要求時間復雜度為 O(N×K),額外空間復雜度為 O(K)。
解答
無論是原問題還是進階問題,都可以用哈希表記錄每個數及其出現的次數,但是額外空間復雜度為 O(N),不符合題目要求,所以本文不再詳述這種簡單的方法。本文提供方法的核心思路是,一次在數組中刪掉 K 個不同的數,不停地刪除,直到剩下數的種類不足 K 就停止刪除,那么,如果一個數在數組中出現的次數大于 N/K,則這個數最后一定會被剩下來。
一次在數組中刪掉 K 個不同的數,不停地刪除,直到剩下的數的種類不足 K,那么,如果某些數在數組中出現次數大于 N/K,則這些數最后一定會被剩下來。原問題中,我們解決了找到出現次數超過 N/2 的數,解決的辦法是立了 1 個候選 cand,以及這個候選的 times 統計。進階問題具體的實現也類似,只要立 K-1 個候選,然后有 K-1 個 times 統計即可,具體過程如下。
遍歷到 arr[i] 時,看 arr[i] 是否與已經被選出的某一個候選相同。
- 如果與某一個候選相同,就把屬于那個候選的點數統計加 1。
- 如果與所有的候選都不相同,先看當前的候選是否選滿了,K-1 就是滿,否則就是不滿:
- 如果不滿,把 arr[i]作為一個新的候選,屬于它的點數初始化為 1。
- 如果已滿,說明此時發現了 K 個不同的數,arr[i]就是第 K 個。此時把每一個候選各自的點數全部減 1,表示每個候選“付出”一個自己的點數。如果某些候選的點數在減1 之后等于 0,則還需要把這些候選都刪除,候選又變成不滿的狀態。
在遍歷過程結束后,再遍歷一次 arr,驗證被選出來的所有候選有哪些出現次數真的大于N/K,打印符合條件的候選。具體請參看如下代碼中的 printKMajor 方法。
package chapter_8_arrayandmatrix;import java.util.Arrays;public class Problem_20_PrintMaxTopK {public static class HeapNode {public int value; // 值是什么public int arrNum; // 來自哪個數組public int index; // 來自數組的哪個位置public HeapNode(int value, int arrNum, int index) {this.value = value;this.arrNum = arrNum;this.index = index;}}public static void printTopK(int[][] matrix, int topK) {int heapSize = matrix.length;HeapNode[] heap = new HeapNode[heapSize];for (int i = 0; i != heapSize; i++) {int index = matrix[i].length - 1;heap[i] = new HeapNode(matrix[i][index], i, index);heapInsert(heap, i);}System.out.println("TOP " + topK + " : ");for (int i = 0; i != topK; i++) {if (heapSize == 0) {break;}System.out.print(heap[0].value + " ");if (heap[0].index != 0) {heap[0].value = matrix[heap[0].arrNum][--heap[0].index];} else {swap(heap, 0, --heapSize);}heapify(heap, 0, heapSize);}}public static void heapInsert(HeapNode[] heap, int index) {while (index != 0) {int parent = (index - 1) / 2;if (heap[parent].value < heap[index].value) {swap(heap, parent, index);index = parent;} else {break;}}}public static void heapify(HeapNode[] heap, int index, int heapSize) {int left = index * 2 + 1;int right = index * 2 + 2;int largest = index;while (left < heapSize) {if (heap[left].value > heap[index].value) {largest = left;}if (right < heapSize && heap[right].value > heap[largest].value) {largest = right;}if (largest != index) {swap(heap, largest, index);} else {break;}index = largest;left = index * 2 + 1;right = index * 2 + 2;}}public static void swap(HeapNode[] heap, int index1, int index2) {HeapNode tmp = heap[index1];heap[index1] = heap[index2];heap[index2] = tmp;}public static int[][] generateRandomMatrix(int maxRow, int maxCol,int maxValue) {if (maxRow < 0 || maxCol < 0) {return null;}int[][] matrix = new int[(int) (Math.random() * maxRow) + 1][];for (int i = 0; i != matrix.length; i++) {matrix[i] = new int[(int) (Math.random() * maxCol) + 1];for (int j = 0; j != matrix[i].length; j++) {matrix[i][j] = (int) (Math.random() * maxValue);}Arrays.sort(matrix[i]);}return matrix;}public static void printMatrix(int[][] matrix) {for (int i = 0; i != matrix.length; i++) {for (int j = 0; j != matrix[i].length; j++) {System.out.print(matrix[i][j] + " ");}System.out.println();}}public static void main(String[] args) {int[][] matrix = generateRandomMatrix(5, 10, 1000);printMatrix(matrix);System.out.println("===========================");printTopK(matrix, 100);} }本題代碼
import java.util.ArrayList; import java.util.List;class Solution {public List<Integer> majorityElement(int[] nums) {ArrayList<Integer> list = new ArrayList<>();if (nums.length <= 2) {list.add(nums[0]);if (nums.length == 2 && nums[0] != nums[1]) list.add(nums[1]);return list;}int n1 = Integer.MAX_VALUE;int n2 = Integer.MAX_VALUE;int n3 = Integer.MAX_VALUE;int c1 = 0; // count n1int c2 = 0;int c3 = 0;for (int n : nums) {if (n == n1) c1++;else if (n == n2) c2++;else if (n == n3) c3++;else {if (c1 == 0) {n1 = n;c1 = 1;} else if (c2 == 0) {n2 = n;c2 = 1;} else if (c3 == 0) {n3 = n;c3 = 1;} else {c1--;c2--;c3--;}}}c1 = c2 = c3 = 0;for (int n : nums) {if (n == n1) c1++;else if (n == n2) c2++;else if (n == n3) c3++;}if (c1 > nums.length / 3) list.add(n1);if (c2 > nums.length / 3) list.add(n2);if (c3 > nums.length / 3) list.add(n3);return list;} }總結
以上是生活随笔為你收集整理的leetcode 229. Majority Element II | 229. 求众数 II(找出现次数超过n/k的元素)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 227. Basic
- 下一篇: 算法设计与分析:芯片测试问题、选择问题详