剑指offer在线编程前20道

本人在做剑指offer试题的过程中所用的方法以及参考别人好的算法,进行了一个总结

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

public class Solution {

  public boolean Find(int target, int [][] array) {

         int len = array[0].length;

         int len1 = array.length;

         for(int i=0;i<len;i++){

               for(int j=0;j<len1;j++){

                      if (target==array[i][j]){

                             return true;

                     }

        }

    }

   return false;

   }

}

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

public class Solution {

public String replaceSpace(StringBuffer str) {

if(str==null){

return null;

}

StringBuilder newStr = new StringBuilder();

for(int i=0;i<str.length();i++){

if(str.charAt(i)==' '){

newStr.append('%');

newStr.append(2);

newStr.append(0);

}else{

newStr.append(str.charAt(i));

}

}

return newStr.toString();

}

}

//在不开辟新的空间的基础上

public class Solution {

     public String replaceSpace(StringBuffer str) {

        int spacenum = 0;//spacenum为计算空格数

        for(int i=0;i<str.length();i++){

            if(str.charAt(i)==' ')

                spacenum++;

        }

        int indexold = str.length()-1; //indexold为为替换前的str下标

        int newlength = str.length() + spacenum*2;//计算空格转换成%20之后的str长 度

        int indexnew = newlength-1;//indexold为为把空格替换为%20后的str下标

        str.setLength(newlength);//使str的长度扩大到转换成%20之后的长度,防止下标越界

        for(;indexold>=0 && indexold<newlength;--indexold){ 

                if(str.charAt(indexold) == ' '){  //

                str.setCharAt(indexnew--, '0');

                str.setCharAt(indexnew--, '2');

                str.setCharAt(indexnew--, '%');

                }else{

                    str.setCharAt(indexnew--, str.charAt(indexold));

                }

        }

        return str.toString();

    }

}

3.输入一个链表,从尾到头打印链表每个节点的值。

/**

* public class ListNode {

* int val;

* ListNode next = null;

*

* ListNode(int val) {

* this.val = val;

* }

* }

*

*/

import java.util.Stack;

import java.util.ArrayList;

public class Solution {

public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {

Stack<Integer> s = new Stack<Integer>();

while(listNode != null){

s.push(listNode.val);

listNode=listNode.next;

}

ArrayList<Integer> list=new ArrayList<>();

while(!s.isEmpty()){

list.add(s.pop());

}

return list;

}

}

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

/**

* Definition for binary tree

* public class TreeNode {

* int val;

* TreeNode left;

* TreeNode right;

* TreeNode(int x) { val = x; }

* }

*/

import java.util.*;

public class Solution {

public TreeNode reConstructBinaryTree(int [] pre,int [] in) {

if(in.length==0||pre.length==0){

return null;

}

TreeNode treeNode=new TreeNode(pre[0]);

for(int i=0;i<in.length;i++){

if(pre[0]==in[i]){

treeNode.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));

treeNode.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));

}

}

return treeNode;

}

}

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

import java.util.Stack;

public class Solution {

Stack<Integer> stack1 = new Stack<Integer>();

Stack<Integer> stack2 = new Stack<Integer>();

public void push(int node) {

stack1.push(node);

}

public int pop() {

if(stack1.isEmpty()&&stack2.isEmpty()){

throw new RuntimeException("Queue is empty");

}

if(stack2.isEmpty()){

while(!stack1.isEmpty()){

stack2.push(stack1.pop());

}

}

return stack2.pop();

}

}

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

import java.util.ArrayList;

public class Solution {

public int minNumberInRotateArray(int [] array) {

int low = 0 ;

int high = array.length - 1;

while(low < high){

int mid = low + (high - low) / 2;

if(array[mid] > array[high]){

low = mid + 1;

}else if(array[mid] == array[high]){

high = high - 1;

}else{

high = mid;

}

}

return array[low];

}

}

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

n<=39

public class Solution {

public int Fibonacci(int n) {

int fb1=1;

int fb2=1;

int fb3=0;

if(n==0){

return 0;

}

else if(n==1||n==2){

return 1;

}else{

for(int i=3;i<=n;i++){

fb3=fb1+fb2;

fb1=fb2;

fb2=fb3;

}

return fb3;

}

}

}

8.一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。代码如下所示:

public class Solution {

public int JumpFloor(int target) {

if(target<=0){

return -1;

}else if(target==1){

return 1;

}else if(target==2){

return 2;

}else{

return JumpFloor(target-1)+JumpFloor(target-2);

}

}

}

9.一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。代码如下所示:

public class Solution {

public int JumpFloorII(int target) {

if(target<=0){

return -1;

}else if(target==1){

return 1;

}else{

return 2*JumpFloorII(target-1);

}

}

}

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

public class Solution {

public int RectCover(int target) {

if(target<=0){

return 0;

}

if(target*2==2){

return 1;

}else if(target*2==4){

return 2;

}else{

return RectCover(target-1)+RectCover(target-2);

}

}

}

11.输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。代码实现如下所示:

public class Solution {

public int NumberOf1(int n) {

int count=0;

int flag=1;

while(flag!=0){

if((n&flag)!=0){

count++;

}

flag=flag<<1;

}

return count;

}

}

//最优解

public class Solution {

public int NumberOf1(int n) {

int count=0;

while(n!=0){

++count;

n=(n-1)&n;

}

return count;

}

}

12.给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。代码实现如下所示:

public class Solution {

public double Power(double base, int exponent) {

double res=1,cuur=base;

int n;

if(exponent>0){

n=exponent;

}else if(exponent<0){

if(base==0){

new Throwable("分母不能为0");

}

n=-exponent;

}else{

return 1;

}

while(n!=0){

if((n&1)==1){

res*=cuur;

}

cuur*=cuur;

n=n>>1;

}

return exponent>0?res:1/res;

}

}

13.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。代码实现如下所示:

public class Solution {

public void reOrderArray(int [] array) {

int k=0;

int temp;

for(int i=0;i<array.length;i++){

if(array[i]%2==0){

k=i;

break;

}

}

int m=k;

for(int j=m+1;j<array.length;j++){

if(array[j]%2!=0){

temp=array[j];

for(int n=j-1;n>=k;n--){

array[n+1]=array[n];

}

array[k]=temp;

k++;

}

}

}

}

14.输入一个链表,输出该链表中倒数第k个结点。代码实现如下所示:

/*

public class ListNode {

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}*/

public class Solution {

public ListNode FindKthToTail(ListNode head,int k) {

ListNode pre=head;

ListNode last=head;

if(head==null||k<=0){

return null;

}

for(int i=1;i<k;i++){

if(last.next!=null){

last=last.next;

}else{

return null;

}

}

while(last.next!=null){

last=last.next;

pre=pre.next;

}

return pre;

}

}

15.输入一个链表,反转链表后,输出新链表的表头。代码实现如下所示:

/*

public class ListNode {

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}*/

public class Solution {

public ListNode ReverseList(ListNode head) {

if(head==null){

return null;

}

ListNode pre=head.next;

ListNode temp=head.next;

head.next=null;

while(pre!=null){

temp=pre.next;

pre.next=head;

head=pre;

pre=temp;

}

return head;

}

}

16.输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。代码实现如下所示:

/*

public class ListNode {

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}*/

public class Solution {

public ListNode Merge(ListNode list1,ListNode list2) {

if (list1==null){

return list2;

}

if (list2==null){

return list1;

}

if (list1==null&&list2==null){

return null;

}

ListNode head;

if (list1.val>list2.val){

head=list2;

list2=list2.next;

head.next=null;

}else{

head=list1;

list1=list1.next;

head.next=null;

}

ListNode pre=head;

ListNode temp;

while(list1!=null && list2!=null){

if (list1.val>list2.val){

temp=list2.next;

pre.next=list2;

pre=pre.next;

pre.next=null;

list2=temp;

}else{

temp=list1.next;

pre.next=list1;

pre=pre.next;

pre.next=null;

list1=temp;

}

}

while(list1!=null){

pre.next=list1;

break;

}

while(list2!=null){

pre.next=list2;

break;

}

return head;

}

}

17.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构),代码实现如下所示:

public class Solution {

public boolean HasSubtree(TreeNode root1,TreeNode root2) {

boolean result = false;

if(root1 != null && root2 != null){

if(root1.val == root2.val){

result = DoesTree1HaveTree2(root1,root2);

}

if(!result){result = HasSubtree(root1.left, root2);}

if(!result){result = HasSubtree(root1.right, root2);}

}

return result;

}

public boolean DoesTree1HaveTree2(TreeNode root1,TreeNode root2){

if(root1 == null && root2 != null) return false;

if(root2 == null) return true;

if(root1.val != root2.val) return false;

return DoesTree1HaveTree2(root1.left, root2.left) && DoesTree1HaveTree2(root1.right, root2.right);

}

}

18.操作给定的二叉树,将其变换为源二叉树的镜像。代码实现如下所示:

/**

public class TreeNode {

int val = 0;

TreeNode left = null;

TreeNode right = null;

public TreeNode(int val) {

this.val = val;

}

}

*/

public class Solution {

public void Mirror(TreeNode root) {

if(root==null){

return;

}

TreeNode temp=root.left;

root.left=root.right;

root.right=temp;

Mirror(root.left);

Mirror(root.right);

}

}

19.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.具体代码实现如下所示:

import java.util.ArrayList;

public class Solution {

public ArrayList<Integer> printMatrix(int [][] matrix) {

ArrayList<Integer> list=new ArrayList();

int row=matrix.length;

int column=matrix[0].length;

int circle=((row<column?row:column)-1)/2+1;

for(int i=0;i<circle;i++){

for(int j=i;j<column-i;j++){

list.add(matrix[i][j]);

}

for(int k=i+1;k<row-i;k++){

list.add(matrix[k][column-i-1]);

}

for(int m=column-i-2;(m>=i&&row-i-1!=i);m--){

list.add(matrix[row-i-1][m]);

}

for(int n=row-i-2;(n>i&&column-i-1!=i);n--){

list.add(matrix[n][i]);

}

}

return list;

}

}

20.定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。具体代码实现如下所示:

import java.util.Stack;

import java.util.Arrays;

public class Solution {

private int size;

private int min=Integer.MAX_VALUE;

private Stack<Integer> minStack=new Stack<>();

private Integer[] elements=new Integer[10];

public void push(int node) {

ensureCapacity(size+1);

elements[size++]=node;

if(node<=min){

minStack.push(node);

min=minStack.peek();

}else{

minStack.push(min);

}

}

private void ensureCapacity(int size) {

int len=elements.length;

if(size>len){

int newLen=(len*3)/2+1;

elements=Arrays.copyOf(elements,newLen);

}

}

public void pop() {

Integer top=top();

if(top!=null){

elements[size-1]=(Integer)null;

}

size--;

minStack.pop();

min=minStack.peek();

}

public int top() {

if(!empty()){

if(size-1>=0){

return elements[size-1];

}

}

return (Integer)null;

}

private boolean empty() {

return size==0;

}

public int min() {

return min;

}

}

猜你喜欢

转载自blog.csdn.net/yangmingtia/article/details/82691408