数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
1 <= 数组长度 <= 50000
思路:
打擂台法:
擂主和打擂者不一样,就减一条命。擂主和打擂者一样,就加一条命。
擂主生命被减为0,就下台,由挑战者上台。
最后在擂台上的人就是答案。
正确性:我们假象:那个传说中出现次数一半以上的数字x和剩下的人对抗,最终结果是,x获胜,生命至少还有1,对吧。
真实情况:不是x的数字不仅会减x的生命值,还会“内耗”,也就是互相减生命,所以无论如何x将是最后的胜利者。
class Solution {public int majorityElement(int[] nums) {int target=nums[0];//擂台上的人int num=1;//擂台上的人的生命for(int i=0;i<nums.length;i++){if(nums[i]!=target){num--;}else{num++;}if(num==0){num=1;target=nums[i];}}return target;}
}
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
思路:快排,根据一趟排出的情况只对一边继续即可。
重点::::::::::
while(i<j && arr[j]>=key)j--;
arr[i]=arr[j];
while(i<j && arr[i]<=key)i++;
arr[j]=arr[i];
不加那个等于号就超时,不知道为啥。
class Solution {public int[] getLeastNumbers(int[] arr, int k) {help(arr,k,0,arr.length-1);return Arrays.copyOf(arr, k);}public void help(int[] arr,int k,int left,int right){if(left>=right || left>=k)return;int key=arr[left];int i=left;int j=right;while(i<j){while(i<j && arr[j]>=key)j--;arr[i]=arr[j];while(i<j && arr[i]<=key)i++;arr[j]=arr[i];}arr[i]=key;if(k <= j) help(arr,k, left, j-1);else help(arr, k, j + 1, right);}
}
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例 1:
输入:
["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]
示例 2:
输入:
["MedianFinder","addNum","findMedian","addNum","findMedian"]
[[],[2],[],[3],[]]
输出:[null,null,2.00000,null,2.50000]
限制:
最多会对 addNum、findMedia进行 50000 次调用。
思路:维护一个大根堆一个小根堆,分别记录小的一半和大的一半。采用任何策略,可以维护两个堆大小一样即可(我的策略中小的一半可以多一个,也就是说多那个中位数)。
class MedianFinder {private PriorityQueue<Integer> maxHeap, minHeap;public MedianFinder() {maxHeap = new PriorityQueue<>(Collections.reverseOrder());minHeap = new PriorityQueue<>();}public void addNum(int num) {maxHeap.offer(num);minHeap.offer(maxHeap.poll());//调整:maxHeap始终=minHeap或minHeap+1if (minHeap.size() > maxHeap.size()) {maxHeap.offer(minHeap.poll());}}public double findMedian() {if (maxHeap.size() == minHeap.size()) {return (maxHeap.peek() + minHeap.peek()) * 0.5;}return maxHeap.peek();}
}/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder obj = new MedianFinder();* obj.addNum(num);* double param_2 = obj.findMedian();*/
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
思路:简单dp不解释。
class Solution {public int maxSubArray(int[] nums) {int ans=Integer.MIN_VALUE;int num=0;for(int i:nums){num=num>0?num+i:i;if(num>ans)ans=num;}return ans;}
}