03.数组中重复的数字

简单,使用hash表即可

  • 一边填入hash表一边判断可以有效的节省空间
    1. class Solution {
    2. public:
    3. int findRepeatNumber(vector<int>& nums) {
    4. unordered_map<int, int> hash;
    5. for(int i = 0; i < nums.size(); i++){
    6. if(hash[nums[i]]){
    7. return nums[i];
    8. }
    9. hash[nums[i]]++;
    10. }
    11. return 0;
    12. }
    13. };

    53-1.在排序数组中查找数字

    这题用到二分法,先找右边界,在找左边界。边界确定就看特殊情况。注意,无论是左闭右开还是左闭右闭都是看l来确定边界
    1. class Solution {
    2. public:
    3. int search(vector<int>& nums, int target) {
    4. int n = nums.size();
    5. int left = 0, right = n;
    6. while(left < right){
    7. int mid = left + (right - left)/2;
    8. if(nums[mid] >= target){
    9. right = mid;
    10. } else {
    11. left = mid + 1;
    12. }
    13. }
    14. int first = left;
    15. left = 0, right = n;
    16. while(left < right){
    17. int mid = left + (right - left)/2;
    18. if(nums[mid] > target){
    19. right = mid;
    20. } else {
    21. left = mid + 1;
    22. }
    23. }
    24. return left -first;
    25. }
    26. };

    53-2 0~n-1中缺失的数字

    笨蛋方法(引以为戒)

    1. class Solution {
    2. public:
    3. int missingNumber(vector<int>& nums) {
    4. if(nums[0] != 0){
    5. return 0;
    6. }
    7. for(int i = 0; i < nums.size(); i++){
    8. if(nums[i] != i){
    9. return i;
    10. }
    11. }
    12. return nums.size();
    13. }
    14. };
    连续两次都想到的是这种笨蛋方法,引以为戒

    二分法

    二分法,判断的依据是,nums[i]==i。这里没想出来太可惜了。返回值需要思考一下,我刚开始的时候返回的是nums[l]-1,没有考虑到数组越界的情况。因为求出来的l就是缺数的位置,直接返回l即可。
    1. class Solution {
    2. public:
    3. int missingNumber(vector<int>& nums) {
    4. int l = 0, r = nums.size(), mid;
    5. while(l < r){
    6. mid = l + (r- l)/2;
    7. if(nums[mid] == mid){
    8. l = mid + 1;
    9. } else {
    10. r = mid;
    11. }
    12. }
    13. return l;
    14. }
    15. };

    04. 二维数组中的查找

    这一题和以前写过的一题非常的相似。想法非常类似,这是一个从右下递增的数组,选取右上的中间数,比目标数小则下移,比目标数大则左移。
    1. class Solution {
    2. public:
    3. bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
    4. if(matrix.size() == 0){
    5. return false;
    6. }
    7. int i = 0, j = matrix[0].size() - 1;
    8. while(j>=0&&i<matrix.size()){
    9. if(matrix[i][j] > target){
    10. j --;
    11. } else if (matrix[i][j] < target){
    12. i ++;
    13. } else {
    14. return true;
    15. }
    16. }
    17. return false;
    18. }
    19. };

    11. 旋转数组的最小数字(二分法/重点)

    本题对应leetcode的153和154两题。非常特殊,使用变化的边界来进行二分查找,主要问题是处理mid 与 r相等的情况。利用了旋转之后的数组最右值得特点,只要大于最右值得都是位于最小值左边,小于最右值得就在最小值或右边。相等的情况,可有可无,因为代表至少有两个值,右边界缩一位即可。
    1. class Solution {
    2. public:
    3. int minArray(vector<int>& numbers) {
    4. int low = 0;
    5. int high = numbers.size() - 1;
    6. while (low < high) {
    7. int pivot = low + (high - low) / 2;
    8. if (numbers[pivot] < numbers[high]) {
    9. high = pivot;
    10. }
    11. else if (numbers[pivot] > numbers[high]) {
    12. low = pivot + 1;
    13. }
    14. else {
    15. high -= 1;
    16. }
    17. }
    18. return numbers[low];
    19. }
    20. };

    50. 第一个只出现一次的字符

    非常简单,hash就解决了,也没有复杂度更小的方法。
    1. class Solution {
    2. public:
    3. char firstUniqChar(string s) {
    4. unordered_map<char, int> hash;
    5. vector<char> vec;
    6. for(auto it : s){
    7. if(hash[it] == 0){
    8. vec.push_back(it);
    9. }
    10. hash[it]++;
    11. }
    12. for(auto it : vec){
    13. if(hash[it] == 1){
    14. return it;
    15. }
    16. }
    17. return ' ';
    18. }
    19. };