LeetCode 解题笔记(一)总

2023-05-16

文章目录

  • 一、常用技巧
  • 二 、常用翻译
  • 三、题目
    • x. 其他
      • 9. 回文数--2021/12/09
      • 11. 盛最多水的容器--2022/01/05
      • 15. 三数之和--2022/01/14
    • 17. 电话号码的字母组合--2022/01/15
    • 20. 有效的括号--2021/12/06
    • 21. 合并两个有序链表--2021/12/08
    • 53. 最大子序和--2021/12/07
    • 55. 跳跃游戏--2021/12/05
    • 70. 爬楼梯--2021/12/10
    • 121. 买卖股票的最佳时机--2021/12/13
    • 141. 环形链表--2021/12/16
    • 169. 多数元素--2021/12/17
    • 283. 移动零--2021/12/12
    • 461. 汉明距离--2021/12/15
    • 448. 找到所有数组中消失的数字--2021/12/11
    • 1636. 按照频率将数组升序排序--2021/12/4

系列篇:     

LeetCode 解题笔记(二)数组篇



● 建议:

1、不会的,没有头绪的,先学习答案,有些方法你脑海中都没有,如何又能想到呢?先学习答案吧
2、暴力解法也是解,先出答案再考虑时间复杂度和空间复杂度
3、选择题目,除了在难度上要循序渐进,还建议在算法上进行划分。目前先刷个100题再说
4、同一类型,批量答题,将有助于系统性的学习!

● 刷题记录

03月09日 更新

在这里插入图片描述


一、常用技巧

● 字符串长度或大小:

s.length();
s.size();

● 反转一个数的技巧

resverdNum = resverdNum *10 + x%10;
x/= 10;

● 指针对应的空位 nullptr

if(digits.empty()) return vector<string>();

● ++写在前面

++i:

● range-based for

string s1 =  "123456";
for (auto i : s1 )  	 //普通方式改变访问
   i ++;           		 //改变字符串的每个字符, 不会改变整个字符串s1(123456)
for(const auto& i : s3)  //常引用方式访问元素,避免拷贝代价 s1(123456)
// i ++;                 //报错
for (auto& i : s2 )      //引用方式访问元素
   i ++;                 //改变字符串的每个字符, 使用引用会改变整个字符串s1(234567)

● vector 相关,(代替数组)

int maxArea(vector<int>& height) { int n = height.size()}  //取大小
vector<int> vret;			//用于返回最终结果vret
vret.push_back(3);   		//在vret中数组最后插入3
vert.pop_back();			//在vret中最后去掉一个数

vector<int> v(201, 0);		//用于存储nums数组中元素的重复次数
vector<int> b(2,-1);        //初始化一个大小为2,值为-1的容器b

void threeSum(vector<int>& nums) {
	vector<vector<int>> ans;                    //二维数组
	ans.push_back( {nums[i], nums[j], nums[k]}; //二维数组添加
...
}

//没有指定 vector 的大小,不能在中间直接插入数据的!

● 普通数组

//初始化
int[] array= new int[5];

● 直接调用函数:交换、快速排序

swap(x,y);                           //值交换直接调用

void fun(vector<int>& nums) {
	std::sort(nums.begin(), nums,end())    //快速排序
	...
}

● 无穷大的数

int inf = 1e9;              //1e9 表示一个大数,记为无穷大

● map、unordered_map、set、unordered_set

其中 unordered_map、unordered_set 用的太多了!
在这里插入图片描述
参考:map,unordered_map,set和unordered_set

● map

优点:有序性,这是map结构最大的优点(map 内部实现了一个 红黑树)

缺点:空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率(低于unorder_map),但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间(但占用的内存比unorder_map低)

适用处:对于那些数据存储有顺序要求的问题,用map会更高效一些

实例:

vector<int> list = { 5,14,34,22,39,5};
map<int, int> map;
for (int i = list.size() - 1; i >= 0; i--) {
	map[i] = list[i];  				                   //倒序插入
}
for (auto num = map.begin(); num  != map.end(); num ++) {
	cout << num->first << ' ' << num->second << endl;  //输出的数是有序的且有两个
	//打印:
	//0 5
	//1 14
	//2 34
	//3 22
	//4 39
	//5 5
}

//find()和count()的输入参数都是key值
cout << map.find(3)->first << "," << map.find(3)->second;  //3,22

//m.count(n)计算下标为n的位置有无数据,有返回1,无返回0
cout << map.count(5);                                       //  1

参考:https://blog.csdn.net/bryant_zhang/article/details/111600209

● unordered_map(无序的映射 )

优点: 因为内部实现了哈希表,因此,其元素的排列顺序是无序的。因此其查找速度非常的快(运行效率快于map),时间复杂度可达到O(1),其在海量数据处理中有着广泛应用

缺点: 哈希表的建立比较耗费时间(unorder_map占用的内存比map要高)

适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用 unordered_map

在这里插入图片描述

vector<int> list = { 5,14,34,22,39,5};
unordered_map<int, int> map;
for (int i = list.size()-1; i>=0; i--) {
	map[i] = list[i];                    //倒序插入
}
for (unordered_map<int, int>::iterator i = map.begin(); i != map.end(); i++) { //auto 更好
	cout << i->first << ' ' << i->second << endl;  //输出的数是有序的且有两个
    /*打印:unordered_map 是基于hash表的,因此元素是无序存储的( 不按键 升序排列)。
	5 5
	4 39
	3 22
	2 34
	1 14
	0 5
	*/
}

//find()和count()的输入参数都是key值
cout << map.find(3)->first << "," << map.find(3)->second;  //3,22

//m.count(n)计算下标为n的位置有无数据,有返回1,无返回0
cout << map.count(5);                                       //  1

//删除下标为 5 的位置
cout << map.erase(5);   

实例2:

leetcode :169. 多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        //哈希, 不用数组因为是不知道有多大;对于乱序问题、查找问题,适用于 unordered_map
        unordered_map<int,int> seen;
        int n = nums.size();
        int majority = 0;
        for(auto const & num : nums) {
            seen[num]++;
            if(seen[num] > n/2) {
                majority = num;
            }
        }
        return majority;
    }
};

实例3: 17. 电话号码的字母组合

unordered_map<char, string> phoneMap{
    {'2', "abc"},
    {'3', "def"},
    {'4', "ghi"},
    {'5', "jkl"},
    {'6', "mno"},
    {'7', "pqrs"},
    {'8', "tuv"},
    {'9', "wxyz"}
};

● set

set 实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。**在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。**平衡二叉检索树使用中序遍历算法,检索效率高于vector、deque和list等容器,另外使用中序遍历可将键值按照从小到大遍历出来。

实例1

vector<int> list = { 5,14,34,22,39,5 };
set<int> set1;
for (int i = list.size() - 1; i >= 0; i--) {
	set1.insert(list[i]);  //倒序插入
}
for (auto num = set1.begin(); num  != set1.end(); num ++) {
	cout << *num << endl;  //输出的数是有序的且只有一个5
	/*打印结果* set 是基于RBT的,因此元素是顺序存储的(默认按 键值 升序排列)。
	5
	14
	22
	34
	39 */
}
cout << *set1.find(5) << endl;   //5
cout <<  set1.count(5) << endl;  //1

● STL 容器: unordered_set

unordered_set的内部实现了一个 哈希表,因此, 其元素的排列顺序是无序的。

实例1:

//#include <unordered_set>
vector<int> list = { 5,14,34,22,39,5 };
unordered_set<int> set;
for (int i = list.size() - 1; i >= 0; i--) {
	set.insert(list[i]);  //倒序插入
}
for (unordered_set<int>::iterator num = set.begin(); num  != set.end(); num ++) {
	cout << *num  << endl;  //输出的数是无序的且只有一个5
	/*打印结果: unordered_set是基于hash表的,因此元素是无序存储的( 不按键值 升序排列)。
	5
	39
	14
	22
	34 */
}
cout <<  *set.find(39) << endl;  //39
cout <<   set.count(14) << endl;  //1

实例2:

//初始化一个结构体
unordered_set<ListNode *> seen;
//判断是否包含某一个元素
seen.count(head);
//添加一个元素
seen.insert(head);

实例三: 217.存在重复元素

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> s;
        for (int x: nums) {
            if (s.find(x) != s.end()) {
                return true;
            }
            s.insert(x);
        }
        return false;
    }
};

二 、常用翻译

revertedNum   //回收的数
merge // 合并
frequency   //频率

三、题目


x. 其他

9. 回文数–2021/12/09

链接:9. 回文数
标签
思路:1. 字符串反转;2. 数字的反转(采用这个),且只需要反转一半,当然奇数需要多反转一下。
注意:1. 特殊数的判定:位数为0的、数字0、负数 2. 奇数和偶数的判定 3.while和for的抉择

class Solution {
public:
    bool isPalindrome(int x) {
        //负数不考虑,末尾为0不考虑
        //0 的特殊性
        if(x<0 || (x%10==0 && x!=0) ) {
            return false;
        }

        int revertedNum = 0;

        while(revertedNum < x) {
            revertedNum = revertedNum * 10 + x%10;
            x /= 10;
        }
        return (x==revertedNum) || (x==revertedNum/10);    
    }
};

11. 盛最多水的容器–2022/01/05

链接: 11. 盛最多水的容器

题目:
在这里插入图片描述
关键词: 双指针

暴力解法:(会超时)

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size();
        int maxarea = 0;
        for(int i=1; i<n; i++) {
            for(int j=0; j<i; j++) {
                maxarea = max(min(height[j], height[i]) * (i-j), maxarea);
            }
        }
        return maxarea;
    }
};

官方答案: 双指针

抛弃长的,以短的边,水只会越来越少。所以只能抛弃短的,以长的为边,水才有可能越来越大~,人生也是如此,知道已经是最差的活法呢,为什么不换一种方式重新开始呢!

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left=0, right=height.size()-1;
        int water = 0;

        while(left < right) {
            int tmp = min(height[left] ,height[right]) * (right - left) ;
            water = max(tmp, water);
            if(height[left] < height[right]) {
                ++ left;
            }
            else {
                -- right; 
            }
        }
        return water;
    }
};

15. 三数之和–2022/01/14

链接:15. 三数之和
在这里插入图片描述

标签: 双指针、排序、数组

我的思路: 三重循环,但是没有考虑重复的,比如 -5,1,1,1,4,4,4 就有多组重复的

思路: 排序+双指针, 排序后,然后固定第一个数,另外两个数从两头加,大了话,右指针减,小了话左指针加,知道 left=right ,然后再去重!

网友简洁版答案:(好理解)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> ret;
        if(n < 3)  return {};            // 特判
        //快速排序
        std::sort(nums.begin(), nums.end());
        //固定第一个数,转化为求两数之和
        for(int i=0; i<n; ++i) {        
            if(nums[i] >0)  return ret;         //第一个数为0,后续也不可能相加为0了,除开0,0,0
            if(i>0 && nums[i] == nums[i-1])  continue;
            int left = i+1, right =n-1;          // 双指针在nums[i]后面的区间中寻找和为0-nums[i]的另外两个数
            while(left < right) {
                if(nums[left] + nums[right] > -nums[i]) {
                    --right;                      // 两数之和太大,右指针左移
                }
                else if(nums[left] + nums[right] < -nums[i]) {
                    ++left;                       // 两数之和太小,左指针右移
                }
                else {
                     // 找到一个和为零的三元组,添加到结果中,左右指针内缩,继续寻找
                    ret.push_back( {nums[i], nums[left], nums[right]} );
                    --right;
                    ++left;
                    // 去重:第二个数和第三个数也不重复选取
                    //  例如: -5,1,1,1,4,4,4  如果用if还是会重复 -5 1 4, 要用while
                    while (left < right && nums[left] == nums[left-1])      left++;
                    while (left < right && nums[right] == nums[right+1])    right--;
                }
            }
        }
        return ret;
    }
};


17. 电话号码的字母组合–2022/01/15

链接: 17. 电话号码的字母组合
在这里插入图片描述
标签: 回溯、哈希表、字符串、广度优先搜索、树

思路: 看答案开始不懂,但用纸笔一步一步拆解跟踪后,便一目了然。主要是画出一个树的结构,树根是出发点,第一层表示第一个数字代表的字母,以此类推…

简单版:

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return vector<string>();
        unordered_map<char,string> phoneMap = {
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };
        vector<string> ans;
        string str = ""; 
        traceback(0, ans, phoneMap, digits, str);
        return ans;
    }
    //                          引用,自己始终要记录;  
    void traceback(int index, vector<string>& ans, unordered_map<char,string> phoneMap, string digits,  string str) {
        //递归,进来就是条件
        if(index == digits.size()) {
            ans.push_back(str);
            return ;                   //可不加,加入好理解
        }
        else {
            //添加过程中的字符
            char digit = digits[index];   //"245" 中的 “2”
            string letters = phoneMap.at(digit);      //也可以直接 phoneMap[digit], 得到“abc”
            for (char letter: letters) {
                str.push_back(letter);  //最后添加单个字符
                traceback(index+1, ans, phoneMap, digits, str);
                str.pop_back();         //移除最后的字符
            }
        }
    }
};

增加引用&、const、auto 后: (要习惯这样用,更加严谨,可读可写,一目了然)

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return vector<string>();
        unordered_map<char,string> phoneMap = {
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };
        vector<string> ans;
        string str = ""; 
        traceback(0, ans, phoneMap, digits, str);
        return ans;
    }
    //                          引用,自己始终要记录;  
    void traceback(int index, vector<string>& ans, const unordered_map<char,string>& phoneMap, const string& digits,  string& str) {
        //递归,进来就是条件
        if(index == digits.size()) {
            ans.push_back(str);
            return ;                   //可不加,加入好理解
        }
        else {
            //添加过程中的字符
            char digit = digits[index];   //"245" 中的 “2”
            const string& letters = phoneMap.at(digit);      //也可以直接 phoneMap[digit], 得到“abc”
            for (const auto& letter: letters) {
                str.push_back(letter);  //最后添加单个字符
                traceback(index+1, ans, phoneMap, digits, str);
                str.pop_back();         //移除最后的字符
            }
        }
    }
};


20. 有效的括号–2021/12/06

链接: 20. 有效的括号
标签: 栈、哈希

class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        if (n % 2 == 1) {
            return false;
        }

        unordered_map<char, char> pairs = {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };

		//C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构。
		//c++ stl栈stack的头文件为: #include <stack>
		//empty() 堆栈为空则返回真
		//pop() 移除栈顶元素
		//push() 在栈顶增加元素
		//size() 返回栈中元素数目
		//top() 返回栈顶元素
        stack<char> stk;
        
        //这个和foreach的for循环一样的,也就是遍历
		//这里的char ch: s就是定义一个遍历字符ch,让它分别等于字符串数组s里面的各个字符,然后执行下面的语句,当c被赋值为s里面所有字符各一次后,就会退出这个循环.
        for (char ch: s) {
        	//如果 hash_map 包含其排序键与参数键匹配的元素,则返回 1;如果 hash_map 不包含具有匹配键的元素,则返回 0
            if (pairs.count(ch)) {    
            	//栈中本身是空, 如果匹配了右键 而此时而栈为空、或者栈顶不等于键值,则不满足条件
                if (stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                //满足条件,移除栈顶的元素
                stk.pop();
            }
            else {
                stk.push(ch);  //  增加一个值(左括号)
            }
        }
        return stk.empty();
    }
};

21. 合并两个有序链表–2021/12/08

链接:21. 合并两个有序链表
标签:链表、迭代
思路:比较两个链表的第一个数就好,谁的小,新建的链表指向谁。
注意:指针的空为nullptr、链表的指针使用->

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        //定义头:方便返回  注意是地址  
        ListNode* listHead = new ListNode(-1);  
        //定义一个跟随的指针
        ListNode* prev = listHead;

        while(l1!=nullptr && l2!=nullptr) {
            if(l1->val <= l2->val) {
                prev->next = l1;
                l1=l1->next;
            }
            else {
                prev->next = l2;
                l2=l2->next;
            }
            prev = prev->next;
        }

        if(l1==nullptr)    prev->next = l2;
        else                prev->next = l1;
        
        return listHead->next;
    }
};

53. 最大子序和–2021/12/07

链接:53. 最大子序和
标签:动态规划、滚动数组
思路:存在最大和:

		f(i) = max{f(i−1)+nums[i], nums[i]}

注意:指针的空为nullptr、链表的指针使用->

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //pre: 加上新来的后当前最大的,  maxAns:历史最大的
        int pre = 0, maxAns = nums[0];
        //for(int i=0; i<nums; i++)
        for(const auto& a: nums) {
        	//如果前边累加后还不如自己本身大,那就把前边的都扔掉,从此自己本身重新开始累加。
            pre = max(pre + a, a);
            maxAns = max(maxAns, pre);
        }
        return maxAns;
    }
};

55. 跳跃游戏–2021/12/05

链接:55. 跳跃游戏
标签: 贪心算法

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int k=0;
        int num = nums.size();
        for(int i=0; i<num; i++ ) {
            if(k<i) return false;
            //获取最大可跳的数
            k = max(k, nums[i] + i);
            //以下可有可无
            if(k >= num-1) return true;
        }
        return true;
    }
};

70. 爬楼梯–2021/12/10

链接:70. 爬楼梯
标签: 动态规划
思路:

//f(1) = 1
//f(2) = 2
//f(3) = f(2) + f(1) = 3
//f(4) = f(3) + f(2) = 5

//再用滚动数组
class Solution {
public:
    int climbStairs(int n) {
        int a=1,b=2,c;
        if(n==1) return c=1;
        if(n==2) return c=2;
        for(int i=3; i<=n; ++i) {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
};



121. 买卖股票的最佳时机–2021/12/13

链接:121. 买卖股票的最佳时机
标签: 动态规划、数组
题目:
在这里插入图片描述
我的答案:

思路: 不断的找最小值,不断计算后面的数与最小值的差值。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int min = prices[0];
        int profit = 0, maxProfit = 0;
        
        for(int i=1; i<n; i++) {
            if(prices[i] <= min) {
                min = prices[i];
            }
            else {
                profit = prices[i] - min;
                if(maxProfit <= profit)
                maxProfit = profit;
            }
        }
        return maxProfit;
    }
};

官方:思路基本一样,但很简洁,学习学习…

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int inf = 1e9;              //1e9 表示一个大数,记为无穷大
        int minprice = inf, maxprofit = 0;
        for (int price: prices) {
            maxprofit = max(maxprofit, price - minprice);
            minprice = min(price, minprice);
        }
        return maxprofit;
    }
};




141. 环形链表–2021/12/16

链接:141. 环形链表
标签: 哈希表、Floyd 判圈算法、链表、双指针
题目:
在这里插入图片描述
官方方法一:

使用哈希表存储所有已经访问过的节点,每次判断是否存在

(我也想到了,但是不会使用)

class Solution {
public:
    bool hasCycle(ListNode *head) {
        unordered_set<ListNode *> seen;
        while (head != nullptr) {
            if(seen.count(head)) {
                return true;
            }
            seen.insert(head);
            head = head->next;
        }
        return false;
    }
};

官方方法二:

Floyd 判圈算法,采用双指针,一快一慢,快的指针每次移动两个,慢的每次移动一个,如果有环则一定相遇,如果到了链表尾没有相遇则不是有环的

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        //双指针
         if( head==nullptr || head->next == nullptr) {
            return false;
        }
        ListNode* fast = head->next;
        ListNode* slow = head;

        while(fast != slow) {
            //不相等就开启下一轮,一定要提前判断空指针,记得从左往右的一个一个判断
            //更加习惯下面的判断,因为第二个已经判断不为空了
            if( fast->next == nullptr || fast->next->next == nullptr) {
                return false;
            }
            //官方:
            // if (fast == nullptr || fast->next == nullptr) {
            //     return false;
            // }

            fast = fast->next->next;
            slow = slow->next;
        }
        return true;
    }
};

169. 多数元素–2021/12/17

链接:169. 多数元素

标签:哈希、数字

方法一:我的方法(哈希方法)

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        //哈希, 不用数组因为是不知道有多大
        unordered_map<int,int> seen;
        int n = nums.size();
        int majority = 0;
        for(auto const & num : nums) {
            seen[num]++;
            if(seen[num] > n/2) {
                majority = num;
            }
        }
        return majority;
    }
};

方法二:官方:哈希映射

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> counts;
        int majority = 0, cnt = 0;
        for (int num: nums) {
            ++counts[num];
            if (counts[num] > cnt) {
                majority = num;
                cnt = counts[num];
            }
        }
        return majority;
    }
};

方法三:官方:
思路:先排序,再用哈希映射




283. 移动零–2021/12/12

链接:283. 移动零
标签: 数组、双指针
题目:
在这里插入图片描述

自答:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n = nums.size();
        int j = 0;
        for(int i=0; i<n; i++) {
        //核心:不是0的,往前挪
            if(nums[i] != 0) {
                nums[j++] = nums[i];
            }
        }

        //后面的补0
        for(; j< n; j++) {
            nums[j] = 0;
        }
    }
};

官方: 双指针

● 使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。

● 右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。

● 左指针左边均为非零数;右指针左边直到左指针处均为零。
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n = nums.size(), left = 0, right = 0;
        while(right < n) {
            if(nums[right]) {
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
};

461. 汉明距离–2021/12/15

链接:461. 汉明距离

标签:位运算

题目:
在这里插入图片描述

1)我的答案:
① 通过异或,可以获取不同位置的值
② 通过取余,求得 1 的个数

class Solution {
public:
    int hammingDistance(int x, int y) {
        int z = x ^ y, ret = 0;

        while (z) {
            if( z%2 ) {
                ret ++;
            }
            z /= 2;
        }
        return ret;
    }
};

2)官方:移位实现位计
① 通过异或,可以获取不同位置的值
② 通过向右移位,1就在最末位,然后与1做与运算

class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s) {
            ret += s & 1;
            s >>= 1;
        }
        return ret;
    }
};


3)官方:Brian Kernighan 算法

在这里插入图片描述

class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s) {
            s &= s - 1;
            ret++;
        }
        return ret;
    }
};

448. 找到所有数组中消失的数字–2021/12/11

链接: 448. 找到所有数组中消失的数字

题目:在这里插入图片描述

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n = nums.size();
        for(auto& num: nums) {
            int x = (num-1) % n;
            nums[x] += n;
        }

        vector<int> ret;
        for(int i=0; i<n; i++) {
            if(nums[i] <= n) {
                ret.push_back(i+1);
            }
        }

        return ret;
    }
};

1636. 按照频率将数组升序排序–2021/12/4

链接: 1636. 按照频率将数组升序排序

标签:排序、vector 容器

思路
① 首先创建一个大小为201的数组vn来存储nums中所有元素的出现次数(元素值-100对应v中下标为0,依次类推)
② 然后按频率低到高、数字大到小 输出下标值到vret返回即可

输入:nums = [1,1,2,2,2,3]
输出:[3,1,1,2,2,2]
解释:'3' 频率为 1'1' 频率为 2'2' 频率为 3
class Solution {
public:
    vector<int> frequencySort(vector<int>& nums)
{
    //定义一个数组,里面包含了-100 到 100 之间出现的个数
    vector<int> vn(201,0);
    //定义一个返回的数组
    vector<int> vret;

    //先求出-100 到 100 之间出现的个数  +100  后  求出0 到 200 之间出现的个数
    for(const auto& a: nums) {
        vn[a+100] ++;
    }

    //频率排序: 最多100, 最多nums.size
    int nSize = nums.size();
    for(int i=1; i<=nSize; i++) {
        //从100 往下 到-100  这样是倒序 但是最大的数字 可以算出来
        for(int j=200; j>=0; j--) {
            //核心为: 从频率递到高,从大到小输出  频率肯定先试只出现一次的,3 
            if(vn[j] == i) {
                for(int k=0; k<i; k++) {
                    vret.push_back(j-100);
                }
            }
        }
    }
    return vret;
}

};

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LeetCode 解题笔记(一)总 的相关文章

  • 36.【linux驱动】spi framebuffer驱动(切换并显示虚拟终端)

    1 framebuffer驱动 2 spi framebuffer驱动 3 spi framebuffer驱动 切换并显示虚拟终端 切换终端输出 接这上一节 spi framebuffer驱动实现了 xff0c 但是只有刷屏 6个虚拟终端并
  • ubuntu 移除PPA

    ubuntu 移除PPA 问题描述解决方案1 移除PPA源2 移除key3 查看那些包被替换4 从官方源下载包并替换5 测试是否替换成功 总结反思 问题描述 试图在ubuntu 20 04上安装Phalcon框架 xff0c 但是发现版本不
  • django内置的密码加密与解密

    Django 内置的User类提供了用户密码的存储 验证 修改等功能 xff0c 默认使用pbkdf2 sha256方式来存储和管理用的密码 django通过PASSWORD HASHERS来设置选择要使用的算法 xff0c 列表的第一个元
  • TF坐标变换的学习

    官方教程 xff1a http wiki ros org tf ROS中的很多软件包都需要机器人发布tf变换树 xff0c 那么什么是tf变换树呢 xff1f 抽象的来讲 xff0c 一棵tf变换树定义了不同坐标系之间的平移与旋转变换关系

随机推荐

  • Docker 服务端口一览

    最近研究微服务 xff0c 使用Docker来进行部署应用 说实话docker是个好东西 xff0c 只要编写好Dockerfile文件和docker compose yml文件 xff0c 便能快速启动并运行相关服务 调试过程中查看服务可
  • 鱼眼镜头的成像原理到畸变矫正(完整版)

    最近刚接触鱼眼相机 xff0c 发现网上资料还是比较零散的 xff0c 于是把搜罗到的资料汇总梳理了一下 这里推荐大家直接看链接6的论文 xff0c 从成像模型到畸变矫正整个过程讲的比较清楚 xff0c 网上很多版本其实都是根据这两篇论文来
  • STM32通过广和通ADP-L610-Arduino进行TCP/IP通信

    STM32通过广和通L610进行TCP IP通信 一 写在前面 本次参加嵌入式大赛 xff0c 使用了广和通的ADP L610 Arduino板子进行通信 项目要求大概是本地上传数据到服务器 xff0c 服务器接收后发送给客户端 xff0c
  • Visual Studio Code Git版本控制 更改语言成英文

    一 初始化git库 新版vscode只能打开一个文件夹 xff0c 当你打开这个文件夹后 xff0c 再点击左边的git控制按钮 xff0c 就会初始化该文件夹为git工作目录 xff0c 如果已经有git控制 xff0c 则不会改变 在v
  • STM8S003F3 开发环境搭建

    硬件相关 芯片介绍 型号 xff1a STM8S003F3P6 xff0c 用的不是ARM内核 STM32用的是ARM xff0c 而是意法半导体自己生产的高性能8位内核 xff1a STM8AF 主要针对汽车电子应用 xff0c 如 xf
  • 教你写Makefile(很全,含有工作经验的)

    原文 转载文 Makefile 值得一提的是 xff0c 在Makefile中的命令 xff0c 必须要以 Tab 键开始 什么是makefile xff1f 或许很多Winodws的程序员都不知道这个东西 xff0c 因为那些Window
  • 与JWT的不解之缘

    jar xff1a maven lt dependency gt lt groupId gt io jsonwebtoken lt groupId gt lt artifactId gt jjwt lt artifactId gt lt v
  • 连接服务器报错:Key exchange was not finished, connection is closed.

    解决方案 xff1a 在 etc ssh sshd config最后添加如下行内容解决问题 KexAlgorithms diffie hellman group1 sha1 diffie hellman group14 sha1 diffi
  • ros多线程管理

    单线程Spinning ros spin 是最简单的单线程自旋 它会一直调用直到结束 用法 ros spin ros spinOnce 另一个单线程spinning是ros spinOnce 它定期调用等待在那个点上的所有回调 用法 ros
  • (每日一读2019.10.24)一种基于通用优化方法的多传感器全局里程计估计框架(VINS-Fusion)

    参考博文 萌新学VINS Fusion 一 特征跟踪 萌新学VINS Fusion 二 特征跟踪 摘要 精确的状态估计是自主机器人的一个基本问题 为了实现局部精确和全局无漂移状态估计 通常将具有互补特性的多个传感器融合在一起 局部传感器 摄
  • (每日一读2019.10.25)一种基于通用优化方法的多传感器局部里程计估计框架(VINS-Fusion)

    摘要 为了提高机器人的鲁棒性和自主性 越来越多的传感器被安装在机器人上 我们已经看到了不同平台上安装的各种传感器套件 例如地面车辆上的立体摄像机 手机上带有IMU 惯性测量单元 的单目摄像机以及空中机器人上带有IMU的立体摄像机 虽然过去已
  • Gazebo模型下载以及配置--解决Gazebo黑屏原因

    前往ExBot ROS专区下载Gazebo模型 https bitbucket org osrf gazebo models downloads 下载后把文件放在 gazebo下的models文件夹中 span class token fu
  • 相机内外参数以及畸变参数

    关于大佬们的一些见解 下面是引用知乎的一段文字 xff1a 我们从单目视觉说起 平时我们都说要做视觉识别 测量云云 xff0c 然后我们就会去拍照 xff0c 再对数字图像做各种处理 xff0c 颜色处理 灰度化 滤波 边缘检测 霍夫变换
  • cmake学习4--自定义编译选项

    CMake 允许为项目增加编译选项 xff0c 从而可以根据用户的环境和需求选择最合适的编译方案 例如 xff0c 可以将 MathFunctions 库设为一个可选的库 xff0c 如果该选项为 ON xff0c 就使用该库定义的数学函数
  • ROS与C++学习1

    ROS与C 入门教程 构建工作空间 构建Catkin包 搭建开发环境 catkin make 编写简单发布节点和订阅节点 编写简单服务端和客户端 使用类方法作为回调函数 使用Timers类 编写高级的发布器和订阅器 Callbacks和Sp
  • IAR的UI界面优化

    显示行数 Tools Options 点击 Editor Tab size xff1a 设置Tab键占用多少个空格Indent size xff1a 应该是设置过行时缩进多少个空格Insert tab xff1a 选了之后在删除Tab时 x
  • MYNTEYE小觅双目摄像头深度版+VINS测试

    小觅双目深度版性能分析 今年 xff08 18年 xff09 11月9号小觅智能科技的深度版双目相机上市 xff0c 于是我在12月初花了2999软妹币购买了120度视角的相机 其中我比较感兴趣的是 双目 43 惯导 43 结构光 的多传感
  • QT+ROS开发

    Qt Creator for ROS 如果想在Qt上进行ros包的开发和GUI界面开发 建议采用下面的方法 http fumacrom com 1mipW Setup Qt Creator for ROS Setup Ubuntu to a
  • PX4、APM无人机仿真连接QGC地面站记录(udp连接、更改home点等)

    文章目录 一 PX41 gazebo 仿真2 连接地面站3 更改 Home点 二 APM 仿真1 执行仿真指令2 连接地面站3 更改 Home 点 本文仅记录仿真指令 xff0c 搭建安装不在此 一 PX4 首先给飞控源码和子目录权限 sp
  • LeetCode 解题笔记(一)总

    文章目录 一 常用技巧二 常用翻译三 题目x 其他9 回文数 2021 12 0911 盛最多水的容器 2022 01 0515 三数之和 2022 01 14 17 电话号码的字母组合 2022 01 1520 有效的括号 2021 12