剑指offer 题目训练一

本文集解答了多个经典的编程问题,包括查找二维数组中的整数、字符串空格替换、链表逆序打印等,并提供了详细的算法思路及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.

题目描述

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

1 4 5  8

3 6 9 11

4 10 12

思路:从左边的第一列最后一行往上与目标target进行比较,如果该值比目标值大,则跳转到上一行,如果该值比目标值小,则目标值只可能存在于该行之中,则在该行从左向右进行遍历。时间复杂度为O(n+m)

public static boolean Find(int target, int [][] array) {
    	int y=array.length-1;
     	int i=0;
     	while(i<array[0].length&&y>=0) {
     		if(array[y][i]>target) {
     			y--;
     		}
     		else if(array[y][i]<target) {
     			i++;
     		}
     		else
     			return true;
     	}
     	return false;
    }

2.

题目描述

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
 思路:直接将StringBuffer对象转化为String对象,然后调用String对象自带的replaceAll方法。
 public String replaceSpace(StringBuffer str) {
	   return str.toString().replaceAll(" ", "%20");
	 }
3.

题目描述

输入一个链表,从尾到头打印链表每个节点的值。
思路:运用两个ArrayList数组,从头到尾遍历整个链表,将每个节点的值添加到第一个ArrayList数组中,再反着遍历第一个ArrayList数组,将数组中的值添加到第二个ArrayList数组中。
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
	       ArrayList<Integer> arraylist=new ArrayList<>();
	       while(listNode!=null) {
	    	   arraylist.add(listNode.val);
	    	   listNode=listNode.next;
	       }
	       ArrayList<Integer>arraylist1=new ArrayList<>();
	       for(int i=arraylist.size()-1;i>=0;i--) {
	    	   arraylist1.add(arraylist.get(i));
	       }
		 return arraylist1;
	  }

思路:借鉴大佬的采用递归的方法。

 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        if(listNode!=null){
            this.printListFromTailToHead(listNode.next);
            arrayList.add(listNode.val);
        }
        return arrayList;
    }

4.

题目描述

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

思路:从头开始遍历先 前序遍历序列,如访问第一个元素1,然后在中序遍历序列中找到该值1,则中序遍历序列 值1左边的数都为其左子树,值1右边的值都为其右子树,在前序遍历中访问的位置 加 该值在中序遍历中左边的个数的数值 都在其左子树中,在前序遍历中访问的位置 加 该值在中序遍历中右边的个数的右边所有数值 都在其右子树中。

        根据上述的描述,采用递归的思想,去生成树。

 public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
	    TreeNode root=reConstructBinaryTree(pre, 0,pre.length-1,in,0,in.length-1);
	    return root;
	}
	 //递归方法
	 //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
	 private TreeNode reConstructBinaryTree(int [] pre,int prestart,int preend,int [] in,int instart,int inend) {
		 if(prestart>preend||instart>inend) {
			 return null;
		 }
		 TreeNode temp=new TreeNode(pre[prestart]);
		 for(int i=instart;i<=inend;i++) {
			 if(in[i]==pre[prestart]) {
			 temp.left=reConstructBinaryTree(pre, prestart+1, prestart+i-instart, in, instart, i-1);
			 temp.right=reConstructBinaryTree(pre, i-instart+prestart+1, preend, in, i+1, inend);
			 }
		 }
		 return temp;
	 }

5.

题目描述

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:两个栈刚好能实现一个队列,队列的要求是先进先出。两个栈,在加入一个新的值时,遍历第一个栈,pop栈中的值,并加入到第二个栈中,然后将新的值加入到空的第一个栈中,再将第二个栈中的值一一压回第一个栈中。

 public void push(int node) {
     while(!stack1.isEmpty()) {
    	 stack2.push(stack1.pop());
     }
     stack1.push(node);
     while(!stack2.isEmpty()) {
    	 stack1.push(stack2.pop());
     }	
    }
    public int pop() {
    	return stack1.pop();
    }

6.

题目描述

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。

n<=39

斐波那契额数列:1 1 2 3 5 8 13 21

F(n)=F(n-1)+F(n-2)

思路:一看到此题,我们就会想到运用递归的想法来解题,思路是对的,但是时间会超限,因为递归重复计算了很多数值。因此我们需要采用迭代的方法来做,当n==1||n==2时返回1,当n>=3时,用两个数来分别记录F(n-1)和F(n-2)进行计算推导即可。

public static int Fibonacci(int n) {
		int a=1,b=1,c=0;
		 if (n<0){
			return 0;
		}
		else if(n==1||n==2)
			return 1;
		else {
			
			for(int i=3;i<=n;i++) {
				c=a+b;
				b=a;
				a=c;
			}
			return c;
		}
        
	 }

7.

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路:一开始我的想法是直接采用数学上的排列组合公式来进行计算,先计算最多能有多少个跳2阶的次数,然后逐级递减这个次数,sum =C(n-k)k+C(n-(k-1))(k-1).....,然后发现当数值大的时候计算Cnk会溢出,因此此想法被遗弃。

    n阶台阶,因为青蛙一次只可以跳上1或2阶台阶,因此跳n阶台阶可以分为先跳n-1台阶再跳一级和先跳n-2阶台阶再一次跳2级,因此F(n)=F(n-1)+F(n-2),推出公式之后就可以按照迭代的思想来做。

 public int JumpFloor(int target) {
       if(target==0) 
       {
    	 return 0;
       }
       else if(target==1) {
    	 return 1;
       }
       else if(target==2) {
    	   return 2;
       }
       else {
    	  int x=1,y=2,z=0;
          for(int i=3;i<=target;i++) {
        	  z=x+y;
        	  x=y;
        	  y=z;
          }
          return z;
       }
	 }

8.

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路: n阶台阶 第一步有n种跳法:跳1阶、跳二阶----跳n阶 

           跳一级,剩下n-1阶,剩下跳法f(n-1)

  跳二级,剩下n-2阶,剩下跳法f(n-2)
  f(n)=f(n-1)+f(n-2)+f(1)
  又因为 f(n-1)=f(n-2)+f(n-3)+...f(1)
  因此 f(n)=2*f(n-1)

 public static int JumpFloorII(int target) {
	    int sum=1;
		 for(int i=1;i<target;i++) {
	    	sum=2*sum;
	    }  
		 return sum;
   // return  1<<--target;
	 }

9.

题目描述

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

1 1 1 1 1 1 1

1 1 1 1 1 1 1

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

思路:2*n矩形覆盖可以看成2*(n-1)矩阵再放一个2*1 和 2*(n-2)矩阵再放两个2*1,因此F(n)=F(n-1)+F(n-2)。

 public static int RectCover(int target) {
         if(target==0) {
        	 return 0;
         } 
		 if(target==1) {
        	  return 1;
          }
          else if(target==2) {
        	  return 2;
          }
          else {
        	  int x=1,y=2,z=3;
        	  for(int i=3;i<=target;i++) {
        		  z=x+y;
        		  x=y;
        		  y=z;
        	  }
        	  return z;
          }
	 }

10.

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:直接采用Integer.toBinaryString方法,将十进制数值转化为二进制字符串,然后判断'1'字符的个数。
public int NumberOf1_1(int n) {
        String s=Integer.toBinaryString(n);
        int sum=0;
        for(int i=0;i<s.length();i++) {
     	   if(s.charAt(i)=='1') {
     		   sum++;
     	   }
        }
        return sum;
}

思路:将十进制数值与1相与来判断最后一位是否为1,然后对数值n进行无符号右移一位,直到n为0为止。

public int NumberOf1_2(int n) {
	   int sum=0;
	   while(n!=0) {
		   sum=sum+(n&1);
		   n=n>>1;
	   }
	   return sum;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值