当前位置:   article > 正文

剑指Offer C++ --- 数组篇2

剑指Offer C++ --- 数组篇2

12.矩阵中的路径

思路:

从矩阵第一个元素开始判断,它是不是word的第一个字符,如果不是,继续判断下一个

如果是,则判断其上,下,左,右只要有一个满足,其是word的第一个字符,继续判断下一个。。。 如果不是,则回到矩阵的位置,继续判断下一个是不是word的开始字符

很明显,要用回溯算法,进行深度遍历

  1. int row;
  2. int col;
  3. bool exist(vector<vector<char>>&board, string word)
  4. {
  5. row = board.size();
  6. col = board[0].size();
  7. for(int i = 0; i < row; ++i)
  8. {
  9. for(int j = 0; j < col; ++j)
  10. {
  11. if(dfs(board,word,i,j,0))
  12. {
  13. return true;
  14. }
  15. }
  16. }
  17. return false;
  18. }
  19. bool dfs(vector<vector<char>>&board,string& word,int i,int j,int k)
  20. {
  21. //矩阵中的字母不合适退出
  22. if(i<0 || i>=row || j<0 || j>=col || board[i][j] != word[k])
  23. {
  24. return false;
  25. }
  26. //完全匹配成功
  27. if(word.size()-1 == k)
  28. {
  29. return true;
  30. }
  31. //能走到这儿,说明board[i][j]的字母与word的字母匹配成功
  32. //board[i][j]置为'\0'
  33. board[i][j] = '\0';
  34. //上 下 左 右进行深度探索
  35. bool res = dfs = (board,word,i+1,j,k+1) || (board,word,i-1,j,k+1)
  36. || (board,word,i,j-1,k+1) || (board,word,i,j+1,k+1);
  37. //回溯过程中,将矩阵中修改的元素重新填回
  38. board[i][j] = word[k];
  39. return res;
  40. }

13.打印从1到最大的n位数

  1. vector<int> printNumbers(int n)
  2. {
  3. int max = pow(10,n) - 1;
  4. vector<int> nums;
  5. nums.reserve(max);
  6. for(int i = 1; i <= max; ++i)
  7. {
  8. nums.emplace_back(i);
  9. }
  10. return nums;
  11. }

14.调整数组顺序使奇数位于偶数之前

思路:首尾开工

  1. vector<int> exchange(vector<int>& nums)
  2. {
  3. int i = 0;
  4. int j = nums.size()-1;
  5. while(i<j)
  6. {
  7. //遇到奇数直接跳过
  8. while(i<j && (nums[i] & 1) == 1)
  9. {
  10. ++i;
  11. }
  12. //遇到偶数直接跳过
  13. while(i<j && (nums[j] & 1) == 0)
  14. {
  15. --j;
  16. }
  17. //交换
  18. if(i < j)
  19. {
  20. int tmp = nums[i];
  21. nums[i] = nums[j];
  22. nums[j] = tmp;
  23. ++i;
  24. --j;
  25. }
  26. }
  27. return nums;
  28. }

15.顺时针打印矩阵

思路:

转化四种状态:

left  ---》 right

top  ---》 bottom

right  ---》left

bottom  ---》 top

退出条件:左边界 > 右边界,上边界 > 下边界

每遍历一次就需要检查一次是否越界

  1. vector<int> spiralOrder(vector<vector<int>>& matrix)
  2. {
  3. //控制列
  4. int left = 0; //左边界
  5. int right = matrix[0].size()-1; //右边界
  6. //控制行
  7. int top = 0; //上边界
  8. int bottom = matrix.size()-1; //下边界
  9. vector<int> vec;
  10. vec.reserve((right+1)*(bottom+1));
  11. while(true)
  12. {
  13. //left -> right
  14. for(int i = left;i<=right;++i)
  15. {
  16. vec.emplace_back(matrix[top][i]);
  17. }
  18. //检查边界,并跳到下一行
  19. if(++top > bottom) break;
  20. //top -> bottom
  21. for(int i = top;i<=bottom;++i)
  22. {
  23. vec.emplace_back(matrix[i][right]);
  24. }
  25. //检查边界,并跳到下一列
  26. if(--right < left) break;
  27. //right -> left
  28. for(int i = right;i>=left;--i)
  29. {
  30. vec.emplace_back(matrix[bottom][i]);
  31. }
  32. //检查边界,并跳到上一行
  33. if(--bottom < top) break;
  34. //bottom -> top
  35. for(int i = bottom;i>=top;--i)
  36. {
  37. vec.emplace_back(matrix[left][i]);
  38. }
  39. //检查边界,并跳到下一列
  40. if(++left > right) break;
  41. }
  42. return vec;
  43. }

16.栈的压入、弹出序列

思路:

借助栈来判断,每向栈内入一个元素,循环判断栈顶元素是否与出栈序列的元素相等,如果相等则出栈,序列向后迭代一个,继续比较。。。

如果栈为空,则出栈序列正确,否则错误

  1. bool validateStackSequences(vector<int>& pushed, vector<int>& popped)
  2. {
  3. statct<int> st;
  4. int i = 0;
  5. for(auto x:pushed)
  6. {
  7. st.push(x);
  8. while(!st.empty() && st.top() == popped[i])
  9. {
  10. st.pop();
  11. i++;
  12. }
  13. }
  14. return st.empty();
  15. }

17.数组出现次数超过一半的数字

思路:假设众数val = x,num = 1,遍历后续元素,如果相等则num+=1,如果不相等,则num -=1

当num = 0时,下一个遍历的元素即就是x,num重新赋值为1

  1. int majorityElement(vector<int>& nums)
  2. {
  3. int x = 0;
  4. int n = 0;
  5. for(auto val : nums)
  6. {
  7. if(n == 0)
  8. {
  9. x = val;
  10. n = 1;
  11. }
  12. else
  13. {
  14. x != val ? n -= 1 : n += 1;
  15. }
  16. }
  17. return x;
  18. }

18.最小的k个数

思路:利用优先级队列构建小根堆,然后取堆顶前k个元素

  1. vector<int> getLeastNumbers(vector<int>& arr, int k)
  2. {
  3. if(k == 0)
  4. {
  5. return vector<int>();
  6. }
  7. //构建小根堆
  8. priority_queue<int,vector<int>,greater<int>> q;
  9. for(auto x : arr)
  10. {
  11. q.push(x);
  12. }
  13. vector<int> vec;
  14. vec.reserve(k);
  15. while(k-- != 0)
  16. {
  17. vec.emplace_back(q.top));
  18. q.pop();
  19. }
  20. return vec;
  21. }

19.有硬币1,3,5若干,求组成金额为11的最小的硬币数

  1. //分治
  2. int func(int n)
  3. {
  4. if(n == 1 || n == 3 || n == 5)
  5. {
  6. return 1;
  7. }
  8. else if(n == 2 || n == 4)
  9. {
  10. return 2;
  11. }
  12. else
  13. {
  14. int n1 = func(n-1)+1;
  15. int n2 = func(n-3)+1;
  16. int n3 = func(n-5)+1;
  17. return min({n1,n2,n3});
  18. }
  19. }
  20. //动态规划
  21. void fun()
  22. {
  23. int v[] = {1,3,5}; //硬币的面额组成
  24. int length = sizeof(v)/sizeof(v[0]);
  25. int c = 11; //面值11
  26. int dp[12]{}; //dp数组,存放最优子结构
  27. for(int i = 1; i <= c; ++i)
  28. {
  29. dp[i] = i; //表示初始全部由1分硬币组成
  30. for(int j = 0; j < length; ++j)
  31. {
  32. if(i >= v[j] && (1 + dp[i-v[j]]< dp[i]]))
  33. dp[i] = 1+dp[i-v[j]];
  34. }
  35. }
  36. cout << dp[c] << endl;
  37. return 0;
  38. }

动态规划的核心思想:将子问题的最优子解存下来,在求取后续子问题时,可以进行复用

20. 斐波那契数列

a.分治

  1. int fib(int n)
  2. {
  3. if(n == 0)
  4. {
  5. return 0;
  6. }
  7. else if(n == 1)
  8. {
  9. return 1;
  10. }
  11. else
  12. {
  13. return fib(n-2)+fib(n-1);
  14. }
  15. }

b.动态规划(递归)

  1. int fib(int n)
  2. {
  3. vector<int> dp(n+1,-1);
  4. return fib(dp,n);
  5. }
  6. int fib(vector<int>& dp,int n)
  7. {
  8. if(dp[n] != -1)
  9. {
  10. return dp[n];
  11. }
  12. if(n == 0)
  13. {
  14. dp[n] = 0;
  15. return dp[n];
  16. }
  17. else if(n == 1)
  18. {
  19. dp[n] = 1;
  20. return dp[n];
  21. }
  22. else
  23. {
  24. dp[n] = fib(n-2) + fib(n-1);
  25. return dp[n];
  26. }
  27. return dp[n];
  28. }

c.动态规划(非递归)

  1. int fib(int n)
  2. {
  3. //状态数组
  4. vector<int> dp(n+2,-1);
  5. //dp[0] = 0, dp[1] = 1, dp[i] = dp[i-2] + dp[i-1] (i>2)
  6. dp[0] = 0;
  7. dp[1] = 1;
  8. if(n == 0 || n == 1)
  9. {
  10. return dp[n];
  11. }
  12. for(int i = 2;i<=n;++i)
  13. {
  14. dp[i] = dp[i-2]+dp[i-1];
  15. }
  16. return dp[n];
  17. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/43698
推荐阅读
相关标签
  

闽ICP备14008679号