2021-10-18 力扣数据结构第一天

只出现一次的数字

点击访问
在这里插入图片描述
思路一:哈希集合表
① 建立哈希集合表unordered_set<int, int> hash
② 遍历数组中的元素,每次遍历判断元素在集合中的个数是否存在,若已经存在就删除,否则就进入集合。最终这个操作使得集合只剩下一个元素,这个元素就是只出现一次的数字。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        auto it = nums.begin();
        unordered_set<int> myHash; 
        while(it != nums.end()){
            if(myHash.count(*it))  //说明集合已经存在这个数了
                myHash.erase(*it);	//删除
            else
                myHash.insert(*it);   //加入
            it++;
        }
        return *myHash.begin();
    }
};

思路二:位运算——XOR
XOR是异或运算,通过下面的例子就可以知道这个方法的妙处:
11001⊗11001 = 00000
11001⊗11000 = 00001
(异或意思是二元组元素相互不一致,且必须是1或0的组合,比如1⊗1=0而1⊗0=1)
这样可以知道在一系列只有一个数字与其他数字不一致时,有下列的等式:
(a_1⊗a_2)…(a_n-2⊗a_n-1)⊗a_n = 0⊗0⊗…⊗0⊗a_n = 0⊗a_n = a_n
因此连续的异或运算之后,最终结果就是只出现一次的数字!

//异或运算
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for(auto i : nums) ret ^= i;
        return ret;
    }
};

多数元素

添加链接描述
在这里插入图片描述
思路一:哈希表
建立哈希表,遍历数组,每次遍历元素都进入哈希表,当哈希值 > [n/2]的时候返回元素即可,否则返回-1

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int n = nums.size() / 2;
        unordered_map<int, int> hash;
        for(auto i : nums){
            if(++hash[i] > n) return i;
        }
        return -1;
    }
};

思路二:排序法
有数学知识可以知,排序后的数组,在array[n/2]位置时对应的数字,它的出现次数总是大于[n / 2]的。原因在于,排序后所有重复的数字都相邻靠近在一起,而中间的数字([n / 2])一定是大于n / 2次数的数字:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() / 2];
    }
};

三数之和

添加链接描述
在这里插入图片描述
思路:双指针+排序
先排序,使得序列有序
i变量初始值为0
然后指针L处于 i + 1,R处于size - 2;
从头开始遍历
如果nums[0]>0,则不存在
否则遍历,每次遍历都要检查是否重合,条件即为:nums[i] == nums[i-1]
后定义sum = nums[i]+nums[L]+nums[R]
若sum>0,说明和大于0,需要减小,所以向左移动R指针,每次移动都要判断是否重合:
while(i<j && nums[–R] == nums[R]);
若sum<0,说明和小于0,需要增大,所以向右移动L指针,每次移动都要判断是否重合:
while(i<j && nums[++i] == nums[i]);

class Solution {
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList();
        int len = nums.length;
        if(nums == null || len < 3) return ans;
        Arrays.sort(nums); // 排序
        for (int i = 0; i < len ; i++) {
            if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
            if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
            int L = i+1;
            int R = len-1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    while (L<R && nums[L] == nums[L+1]) L++; // 去重
                    while (L<R && nums[R] == nums[R-1]) R--; // 去重
                    L++;
                    R--;
                }
                else if (sum < 0) L++;
                else if (sum > 0) R--;
            }
        }        
        return ans;
    }
}
/*
from作者:guanpengchn
链接:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值