数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 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+1
if (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;
}
}