169. 多数元素
方法一:利用哈希表来找出现次数大于n/2的元素,没有啥难度
class Solution {
public int majorityElement(int[] nums) {
//根据题意一定要分析出多数元素一个数组中只能有一个数
int n = nums.length;
int num = 0;
Map<Integer,Integer> map = new HashMap<>();
for(int x: nums){
map.put(x,map.getOrDefault(x,0)+1);
if(map.get(x) > n/2){
num = x;
}
}
return num;
}
}
方法二:新思想:
摩尔投票法思路
候选人(cand_num)初始化为nums[0],票数count初始化为1。
当遇到与cand_num相同的数,则票数count = count + 1,否则票数count = count - 1。
当票数count为0时,更换候选人,并将票数count重置为1。
遍历完数组后,cand_num即为最终答案。
为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”。
class Solution {
public int majorityElement(int[] nums) {
int x = nums[0];
int count = 1;
for(int i=1;i<nums.length;i++){
if(x == nums[i]){
count++;
}else{
count--;
}
if(count == 0){
x = nums[i];
//卡在这一步,换数后忘了再把count也重新赋值为1
count = 1;
}
}
return x;
}
}
287. 寻找重复数
方法一:无脑暴力法
class Solution {
public int findDuplicate(int[] nums) {
int num = nums[0];
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i++){
if(nums[i] == nums[i+1]){
num = nums[i];
}
}
return num;
}
}
方法二:函数思想
class Solution {
public int findDuplicate(int[] nums) {
//将题目给的特殊的数组当作一个链表来看,数组的下标就是指向元素的指针,把
//数组的元素也看作指针。如 0 是指针,指向 nums[0],而 nums[0] 也是针,
//指向 nums[nums[0]].
int fast = 0;
int slow = 0;
int c = 0;
while(true){
// nums[fast] = nums[nums[fast]];
fast = nums[nums[fast]];//快指针,相当于 .next.next
slow = nums[slow]; //慢指针,相当于.next
if(fast == slow){
break;
}
}
//难点:找到重合后清零然后同步走
while(nums[c] != nums[slow]){
c = nums[c];
slow = nums[slow];
}
return nums[slow];
}
}
162. 寻找峰值
class Solution {
public int findPeakElement(int[] nums) {
int left = 0;
int right = nums.length-1;
while(left < right){
int mid = left + (right - left)/2;
if(nums[mid] > nums[mid+1]){
//right = mid-1;
//right可能就是峰顶
right = mid;
}else{
left = mid+1;
}
}
return left;
}
}
思路:
爬山,如果你往下坡方向走,也许可能遇到新的山峰,但是也许是一个一直下降的坡,最后到边界。但是如果你往上坡方向走,就算最后一直上的边界,由于最边界是负无穷,所以就一定能找到山峰,总的一句话,往递增的方向上,二分,一定能找到,往递减的方向只是可能找到,也许没有。