title: LC101の8. 数学
date: ‘2021-07-20 09:50:06’
tags: [数学]
categories:

  • 动手敲敲
  • 算法刷题

公倍数与公因数

辗转相除法

  1. int gcd(int a, int b) {
  2. return b == 0 ? a : gcd(b, a% b);
  3. }
  4. int lcm(int a, int b) {
  5. return a * b / gcd(a, b);
  6. }

扩展欧几里得

  1. int xGCD(int a, int b, int &x, int &y) {
  2. if (!b) {
  3. x = 1, y = 0;
  4. return a;
  5. }
  6. int x1, y1, gcd = xGCD(b, a % b, x1, y1);
  7. x = y1, y = x1 - (a / b) * y1;
  8. return gcd;
  9. }

质数

204. 计数质数

埃氏筛

  1. int countPrimes(int n) {
  2. vector<int> isPrime(n, 1);
  3. int ans = 0;
  4. for (int i = 2; i < n; ++i) {
  5. if (isPrime[i]) {
  6. ans += 1;
  7. if ((long long)i * i < n) {
  8. for (int j = i * i; j < n; j += i) {
  9. isPrime[j] = 0;
  10. }
  11. }
  12. }
  13. }
  14. return ans;
  15. }

数字处理

504. 七进制数

  1. string convertToBase7(int num) {
  2. bool flag = false;
  3. string ans = "";
  4. if(num < 0){
  5. num = -num;
  6. flag = true;
  7. }
  8. do{
  9. ans += to_string(num % 7);
  10. num /= 7;
  11. }while(num);
  12. reverse(ans.begin(), ans.end());
  13. return flag? "-" + ans: ans;
  14. }

172. 阶乘后的零

  1. int trailingZeroes(int n) {
  2. int ans = 0;
  3. for (int i = 5; i <= n; i += 5) {
  4. for (int x = i; x % 5 == 0; x /= 5) {
  5. ++ans;
  6. }
  7. }
  8. return ans;
  9. }

415. 字符串相加

  1. string addStrings(string num1, string num2) {
  2. int i = num1.length() - 1, j = num2.length() - 1, add = 0;
  3. string ans = "";
  4. while (i >= 0 || j >= 0 || add != 0) {
  5. int x = i >= 0 ? num1[i] - '0' : 0;
  6. int y = j >= 0 ? num2[j] - '0' : 0;
  7. int result = x + y + add;
  8. ans.push_back('0' + result % 10);
  9. add = result / 10;
  10. i --;
  11. j --;
  12. }
  13. reverse(ans.begin(), ans.end());
  14. return ans;
  15. }

326. 3 的幂

  1. bool isPowerOfThree(int n) {
  2. while (n && n % 3 == 0) {
  3. n /= 3;
  4. }
  5. return n == 1;
  6. }

随机与取样

384. 打乱数组

经典的 Fisher-Yates 洗牌算法,原理是通过随机交换位置来实现随机打乱。

  1. class Solution {
  2. vector<int> origin;
  3. public:
  4. Solution(vector<int> nums): origin(std::move(nums)) {}
  5. vector<int> reset() {
  6. return origin;
  7. }
  8. vector<int> shuffle() {
  9. if (origin.empty()) return {};
  10. vector<int> shuffled(origin);
  11. int n = origin.size();
  12. // 可以使用反向或者正向洗牌,效果相同。
  13. // 反向洗牌:
  14. for (int i = n - 1; i >= 0; --i) {
  15. swap(shuffled[i], shuffled[rand() % (i + 1)]);
  16. }
  17. // 正向洗牌:
  18. // for (int i = 0; i < n; ++i) {
  19. // int pos = rand() % (n - i);
  20. // swap(shuffled[i], shuffled[i+pos]);
  21. // }
  22. return shuffled;
  23. }
  24. };

528. 按权重随机选择

题目大意:按权重随机返回数字

  1. class Solution {
  2. vector<int> sums;
  3. public:
  4. Solution(vector<int> weights): sums(std::move(weights)) {
  5. partial_sum(sums.begin(), sums.end(), sums.begin());
  6. }
  7. int pickIndex() {
  8. int pos = (rand() % sums.back()) + 1;
  9. return lower_bound(sums.begin(), sums.end(), pos) - sums.begin();
  10. }
  11. };

382. 链表随机节点

题目大意:随机返回链表的一个节点

  1. class Solution {
  2. ListNode* head;
  3. public:
  4. Solution(ListNode* n): head(n) {}
  5. int getRandom() {
  6. int ans = head->val;
  7. ListNode* node = head->next;
  8. int i = 2;
  9. while (node) {
  10. if ((rand() % i) == 0) {
  11. ans = node->val;
  12. }
  13. ++i;
  14. node = node->next;
  15. }
  16. return ans;
  17. }
  18. };

练习