当前位置:   article > 正文

牛客网 剑指OFFER 编程题记录1_list.add(0,tmp.val)

list.add(0,tmp.val)

1. 数组: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

自己编的乱七八糟,用了40行java代码.记录下评论区大神们的思路和操作.

首选: JS做法,最简单最好记: return array.toString().split(',').includes(target.toString())    (注意,JS后面没有分号)

最精妙做法: 当成二维矩阵,从左下角往右上找,如果比左下角元素大,就往右边找;反之就往上找.然后又自己写了一遍.

  1. public class Solution {
  2. public boolean Find(int target, int [][] array) {
  3. int row = array.length;
  4. int col = array[0].length;
  5. if(row!=0&&col!=0){
  6. //从左下角往上和右找
  7. int left = row-1;
  8. int down = 0;
  9. while(left>=0&&down<=(col-1)){
  10. if(target==array[left][down])return true;
  11. else {
  12. if(target<array[left][down]){
  13. left--;
  14. }else{
  15. down++;
  16. }
  17. }
  18. }
  19. return false;
  20. }else{
  21. return false;
  22. }
  23. }
  24. }

2. 字符串: 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

这个回顾复习了一下java里的String函数,

一个%20替换一个空格: return str.toString().replaceAll("\\s","%20");

如果是一个%20替换一个或多个空格: return str.toString().replaceAll("\\s+","%20");

这里要注意的是一个或多个空格的正则表达式: "\\s+", split也是这个用法.

然后看了一下评论区大家的做法,感觉自己有点投机取巧,所以又写了一遍.

  1. public class Solution {
  2. public String replaceSpace(StringBuffer str) {
  3. String ss = str.toString();
  4. String result=""; //注意初始化,否则后面用不了
  5. for(int i=0;i<ss.length();i++){
  6. char c = ss.charAt(i);
  7. if(c == ' '){
  8. result += "%20";
  9. }else{
  10. result += c;
  11. }
  12. }
  13. return result;
  14. }
  15. }

3. 输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

解法1.这里注意一个list的功能,add(index,element),直接将遍历的元素插到ArrayList的起始位置即可。

  1. import java.util.ArrayList;
  2. public class Solution {
  3. public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
  4. ArrayList<Integer> list = new ArrayList<>();
  5. ListNode tmp = listNode;
  6. while(tmp!=null){
  7. list.add(0,tmp.val);
  8. tmp=tmp.next;
  9. }
  10. return list;
  11. }
  12. }

解法2. 用递归,这样就最先插链表的最后一个元素了。这里注意递归返回的那个list一定只有一个。

  1. import java.util.ArrayList;
  2. public class Solution {
  3. //成员变量
  4. ArrayList<Integer> list = new ArrayList<>();
  5. public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
  6. ListNode tmp = listNode;
  7. if(tmp!=null){
  8. printListFromTailToHead(tmp.next);
  9. list.add(tmp.val);
  10. }
  11. return list;
  12. }
  13. }

4. 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

这道题就涉及树的算法了,全忘了,只能从头捡起。看完解法之后我就开始自己编程了,没想到调入了一个binarySearch的陷阱里。先上解法,我的思路完全正确,而且做法也是最简洁的,结果就是不知道为什么错,直到后来直接复制粘贴别人的代码,才发现这个binarySearch的错。

  1. import java.util.Arrays;
  2. public class Solution {
  3. public TreeNode reConstructBinaryTree(int[] pre,int[] in) {
  4. if(pre.length==0){
  5. return null;
  6. }
  7. int rootval = pre[0];
  8. TreeNode root = new TreeNode(rootval);
  9. if(pre.length==1){
  10. return root;
  11. }
  12. int rootIndex = 0;
  13. //这一步,我之前用binarySearch,然后真的大错特错,怎么都没想到是这出了问题
  14. for(int i=0;i<in.length;i++){
  15. if(in[i]==rootval){
  16. rootIndex=i;
  17. break;
  18. }
  19. }
  20. root.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,rootIndex+1),
  21. Arrays.copyOfRange(in,0,rootIndex));
  22. root.right =reConstructBinaryTree(Arrays.copyOfRange(pre,rootIndex+1,pre.length),
  23. Arrays.copyOfRange(in,rootIndex+1,in.length));
  24. return root;
  25. }
  26. }

注意:binarySearch是二分查找法,在对无序数组查找时,非常容易出现找不着的情况。使用二分搜索法来搜索指定的 int 型数组,以获得指定的值。必须在进行此调用之前对数组进行排序(通过 sort(int[]) 方法)。如果没有对数组进行排序,则结果是不确定的。以下为例:所以对于无序数组查找时,千万不要用这个方法。

5. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。比较简单,属于考思路类型。push操作都push到一个栈中,只有在pop时,将栈1的所有元素弹出,再压入栈2,这样从栈2再弹出的就是队列顺序了.

  1. import java.util.Stack;
  2. public class Solution {
  3. Stack<Integer> stack1 = new Stack<Integer>();
  4. Stack<Integer> stack2 = new Stack<Integer>();
  5. //队列先进先出,栈先进后出,把推进栈1的倒到栈2,再从栈2倒出来即可。
  6. public void push(int node) {
  7. stack1.push(node);
  8. }
  9. public int pop() {
  10. if(stack2.empty()){
  11. while(!stack1.empty()){
  12. stack2.push(stack1.pop());
  13. }
  14. }
  15. int node = stack2.pop();
  16. return node;
  17. }
  18. }

6. 旋转数组: 这个是二分查找问题.把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

难点在于,数组中的非递减顺序.

二分查找的做法: 为了避免出现a[mid]=a[left]=a[right]的情况,先将left和light值不断后移和前移使a[left],a[right]不相等. 然后再不断缩小查找范围,直到出现a[left]<a[right],就可以返回最小值a[left]了.(因为在旋转数组中,最左边小于最右边时,那么一定有最左边为最小值).缩小查找范围时,a[mid]如果>=a[left],那么说明a[mid]是左半边非递减数组的,则最小值在mid的右边.反之,a[mid]是右边非递减数组的,则最小值在mid及其mid的左边.

  1. import java.util.ArrayList;
  2. public class Solution {
  3. public int minNumberInRotateArray(int [] array) {
  4. if(array.length==0){
  5. return 0;
  6. }
  7. int left = 0;
  8. int right = array.length - 1;
  9. //避免出现[1,1,1,0,1]的情况,先让left和right做个比较
  10. while((right>left)&&array[left] == array[right]){
  11. left++;
  12. right--;
  13. }
  14. //二分查找
  15. while(array[left]>array[right]){
  16. //mid属于中间值,根据中间值的大小判断最小值在哪半边
  17. int mid = left + (right - left)/2;
  18. //中间值大于left时,说明mid在左半边递增数组,那么最小值在mid右边
  19. if(array[mid]>=array[left]){
  20. left = mid+1;
  21. }else{
  22. //小于left说明mid在右半边递增数组,则最小值在mid及其左边
  23. right = mid;
  24. }
  25. }
  26. return array[left];
  27. }
  28. }

7. 斐波那契: 从0开始的斐波那契数列.虽然递归是最简单的,但内存占用过大,所以还是稳妥一点选循环吧.

  1. public class Solution {
  2. public int Fibonacci(int n) {
  3. int a0 = 0;
  4. int a1 = 1;
  5. if(n==0)return a0;
  6. if(n==1)return a1;
  7. int result =0;
  8. for(int i=2;i<=n;i++){
  9. result = a0+a1;
  10. a0 = a1;
  11. a1 = result;
  12. }
  13. return result;
  14. }
  15. }

8. 递归: 跳台阶: 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。核心思路: JumpFloor(n) = JumpFloor(n-1) + JumpFloor(n-2), 因此又变成了斐波契那问题.

  1. public class Solution {
  2. public int JumpFloor(int target) {
  3. int n=target;
  4. if(n<=0)return 0;
  5. if(n==1)return 1;
  6. if(n==2)return 2;
  7. int f1 = 1;
  8. int f2 = 2;
  9. int result=0;
  10. for(int i=3;i<=n;i++){
  11. result = f1+f2;
  12. f1 = f2;
  13. f2 = result;
  14. }
  15. return result;
  16. }
  17. }

9. 变态跳台阶(递归).一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

两个思路: 1. 青蛙跳台阶数f(n) = f(n-1)+f(n-2)+...+f(1)+1; 然后根据这个迭代着算一下

2. f(n) = f(n-1)+f(n-2)+...+f(1)+1;

 f(n-1) =            f(n-2)+...+f(1)+1;

f(n)-f(n-1)=f(n-1), 所以,f(n)=2*f(n-1),这样计算出来就很快了.首选2做法.不过1做法比较容易想.

  1. public class Solution {
  2. public int JumpFloorII(int target) {
  3. int n = target;
  4. if(n<=0)return 0;
  5. if(n==1)return 1;
  6. if(n==2)return 2;
  7. int[] a= new int[n+1];
  8. a[0] = 1;
  9. a[1] = 1;
  10. a[2] = 2;
  11. for(int i=3;i<=n;i++){
  12. a[i] = 2*a[i-1];
  13. }
  14. return a[n];
  15. }
  16. }

10. 递归: 矩形覆盖: 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

f(1)=1;f(2)=2;f(3)=3;f(4)=5;...;f(n) = f(n-1)+f(n-2)

  1. public class Solution {
  2. public int RectCover(int target) {
  3. int n = target;
  4. int a1 = 1;
  5. int a2 = 2;
  6. if(n<=0)return 0;
  7. if(n==1)return a1;
  8. if(n==2)return a2;
  9. int result = 0;
  10. for(int i=3;i<=n;i++){
  11. result = a1+a2;
  12. a1 = a2;
  13. a2 = result;
  14. }
  15. return result;
  16. }
  17. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/信息技术墨韵书生/article/detail/62892
推荐阅读
相关标签
  

闽ICP备14008679号