校招必备之剑指offer JAVA 全代码多实现【11~20】

4 篇文章 0 订阅
3 篇文章 0 订阅

校招必备之剑指offer JAVA 全代码多实现【1~10】

校招必备之剑指offer JAVA 全代码多实现【11~20】

校招必备之剑指offer JAVA 全代码多实现【21~30】

 

11、题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

 思路1:直接暴力跑。只是需要注意存在指数可能为负,处理一下即可。时间复杂度为O(N),别看虽然是O(N),但是如果是非常大的指数级,仍然需要跑很久。

public class Solution {
    public double Power(double base, int exponent) {
        if(base==0) return 0;
        if(exponent==0) return 1;
        double res=1;
        if(exponent<0){
            base=1/base;
            exponent=-exponent;
        }
        while(exponent>0){
            exponent--;
            res*=base;
        }
        return res;
  }
}

思路2:快速幂,推荐https://blog.csdn.net/qq_19782019/article/details/85621386这篇文章。时间复杂度大概在O(log2N)

public class Solution {
    public double Power(double base, int exponent) {
        double res=1;
        if(exponent<0){
             base=1/base;
             exponent=-exponent;
        }
        while(exponent!=0){
            if(exponent%2==1){
               
                res*=base;
            }
            exponent=exponent>>1;
            base*=base;
        }
        return res;
  }
}

 

12、题目描述

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

思路1:使用额外空间。用两个队列分别存。时间复杂度O(N) 空间复杂度O(N)

import java.util.ArrayDeque;
import java.util.Deque;
public class Solution {
    public void reOrderArray(int [] array) {
         if (array == null || array.length == 0) {
            return;
        }
        Deque<Integer> deque1=new ArrayDeque();//存奇数
        Deque<Integer> deque2=new ArrayDeque();//存偶数
        for(int i:array){
            if(i%2==1){
                deque1.offer(i);
            }else{
                deque2.offer(i);
            }
        }
        int i=0;
        while(!deque1.isEmpty()){
            array[i++]=deque1.poll();
        }
        while(!deque2.isEmpty()){
            array[i++]=deque2.poll();
        }
    }
}

思路2:类似冒泡排序,从后面找起,找到的第一个偶数依次交换到最后,然后往前遍历。时间复杂度O(N^2),空间复杂度O(1)

import java.util.ArrayDeque;
import java.util.Deque;
public class Solution {
    public void reOrderArray(int [] array) {
         if (array == null || array.length == 0) {
            return;
        }
        int temp=0;
        int count=0;//记录第几个偶数
       for(int i=array.length-1;i>=0;i--){
            if(array[i]%2==0){
            for(int j=i;j<array.length-1-count;j++){
                 temp=array[j];
                 array[j]=array[j+1];
                 array[j+1]=temp;
            }
               count++;
           }
          
      }
    }
}

 

13、题目描述

输入一个链表,输出该链表中倒数第k个结点。

思路1:第一反应。也是比较垃圾的想法。遍历两次O(N)

/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        int count=0;
        ListNode cur=head;
        while(cur!=null){
            cur=cur.next;
            count++;
        }
        ListNode node=head;
        if(count<k) return null;
        while(count>k){
            count--;
            node=node.next;
        }
        return node;
        
    }
}

思路2:别人的想法。只需要遍历一次,用两个指针,一个先走K-1步,然后当先走的到最后时,后面一个则是倒数第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) {
        int count=0;
        ListNode fast=head;
        ListNode slow=head;
        
        while(k>0){
            k--;
            if(fast!=null){
                fast=fast.next;
            }else{
                return null;
            }
            
        }
        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
        
    }
}

13、题目描述

输入一个链表,反转链表后,输出新链表的表头。

 思路1:头插法,新建一个指向null的头结点,然后不断头插。

/*
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 newhead=null;
        ListNode next=head.next;;
        while(head.next!=null){
            head.next=newhead;
            newhead=head;
            head=next;
            next=next.next;
        }
        head.next=newhead;
        newhead=head;
        return newhead;
    }
}

思路2:利用栈,先进先出。注意这里需要将最后一个节点指向null,否则最后两个节点循环指向,死循环超时

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.*;
public class Solution {
    public ListNode ReverseList(ListNode head) {
        Stack<ListNode> stack=new Stack<>();
        while(head!=null){
            stack.push(head);
            head=head.next;
        }
        ListNode newhead=new ListNode(0);
        ListNode cur=newhead;
        while(!stack.isEmpty()){
            cur.next=stack.pop();
            cur=cur.next;
        }
        cur.next=null;
        return newhead.next;
    }
}

14、题目描述

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

思路:很简单的一道题,双指针分别比较,然后指向新链表。好像方法就一个。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode p=list1;
        ListNode q=list2;
        ListNode newhead=new ListNode(0);
        ListNode cur=newhead;
        while(p!=null&&q!=null){
            if(p.val<q.val){
                cur.next=p;
                p=p.next;
            }else{
                cur.next=q;
                q=q.next;
            }
            cur=cur.next;
        }
        if(p==null){
            cur.next=q;
        }
        if(q==null){
            cur.next=p;
        }
        return newhead.next;
    }
}

15、题目描述

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路:感觉这题还是有一些难的,思考的时候逻辑有些乱了。看了别人的过程才理清。貌似没有第二种解法,本来想先前序遍历输出到一个数组中,然后判断两个数组是否包含关系,后来仔细想想好像不行毙掉了。

首先判断子结构而不是子树,所谓子树,以代码注释中的为例, 以2 、3 为根节点的是这个大树的子树。而2、3的子树不是大树的子树。子结构就是包含关系,2、3的子树可以是1的子结构。简而言之,子树一定是子结构,子结构不一定是子树

我们判断是否是子结构,可以通过以下步骤,

1)首先判断根节点是否相同,如果不同,肯定不是子结构。

2)如果相同,那么递归左右节点。

重复1)2)直到B被遍历完,如果A先遍历完,而B未遍历完,则不是子结构。

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }
            1
          2   3
        4  5 6 7
       8 9
}
*/
import java.util.*;
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root2==null||root1==null) return false;
        boolean res=false;
        if(root1.val==root2.val){//如果找到相同的根节点,就以此遍历进行查找比较,返回结果
            res=judge(root1,root2);
        }
        if(!res){//如果判断不相同,则以左右节点继续寻找下一个相同的节点
            res=HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
        }
       
        return res;
    }

  
    public boolean judge(TreeNode A,TreeNode B){
        if(B==null) return true;//B要在前,因为我们关心B是否能遍历完,如果遍历完就说明能。如果A在前,
        //出现一种情况,A、B同时遍历完,应该判断true,但由于A在前返回false
        if(A==null) return false;
        if(A.val!=B.val) return false;
        return judge(A.left,B.left)&&judge(A.right,B.right);
        
    }
}

16、题目描述

操作给定的二叉树,将其变换为源二叉树的镜像。

思路:递归交换左右节点。好像别的方法都大同小异,没啥区别。

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
import java.util.*;
public class Solution {
    public void Mirror(TreeNode root) {
       if(root==null) return;
       exChange(root);
        
    }
    public void exChange(TreeNode parent){
        if(parent==null) return;
        TreeNode left=parent.left;
        TreeNode right=parent.right;
        if(left==null&&right==null) return;
        parent.left=right;
        parent.right=left;
        exChange(left);
        exChange(right);
    }
}

17、题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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.*;
/*
    1  2  3  4
    5  6  7  8
    9  10 11 12
    13 14 15 16
*/
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list=new ArrayList<>();
        int m=matrix.length;
        if(m==0) return list;
        int n=matrix[0].length;
        int v=0,h=0;//下界
        int i=0,j=0;//坐标
        while(i>=h&&j>=v&&i<m&&j<n){
            while(j<n){
               list.add(matrix[i][j++]);
            }
            h++;
            j--;
            i++;//此处必须先加1,然后和边缘判断,否则的话会再往回重复打印一遍
            if(i>=m) break;
            while(i<m){
                list.add(matrix[i++][j]);
            }
            m--;
            i--;
            j--;
            if(j<v) break;
            while(j>=v){
                list.add(matrix[i][j--]);
            }
            n--;
            j++;
            i--;
            if(i<h) break;
            while(i>=h){
                list.add(matrix[i--][j]);
            }
            v++;
            i++;
            j++;
            if(j>=n) break;
        }
        return list;
    }
}

思路2:找机会补充一下。方法好像蛮多的,但是这题好麻烦,不想做了。有机会再补

18、题目描述

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

思路:用两个栈,一个栈正常存数,另一个栈用来存历史的最小数。

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1=new Stack<>();
    Stack<Integer> stack2=new Stack<>();
    public void push(int node) {
        stack1.push(node);
        if(!stack2.isEmpty()){
           if(stack2.peek()>node){
               stack2.push(node);
           }
        }else stack2.push(node);
    }
    
    public void pop() {
        int x=stack1.pop();
        if(stack2.peek()==x){
            stack2.pop();
        }
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        return stack2.peek();
    }
}

19、题目描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:用双指针,分别指向入栈序列和出栈序列。如果所指元素不相等,则说明入栈,直到入栈序列跑完,如果相等就说明入栈后立即出栈。

接下来跑出栈序列,如果出栈序列的元素,不等于栈内元素,则说明不是对应的出栈序列。方法都差不多。

import java.util.*;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
       Stack<Integer> stack=new Stack<>();
       int n=pushA.length-1;
       int j=0;
       for(int i=0;i<=n;i++){
          if(pushA[i]!=popA[j]){
              stack.push(pushA[i]);
          }else j++;
       }
       while(j<=n){
           if(popA[j++]!=stack.pop()){
               return false;
           }
       }
        return true;
    }
}

20、题目描述

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:其实就是层次遍历,每一行从上到下依次打印。借用队列的bfs。

import java.util.*;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        Queue<TreeNode> queue=new LinkedList<>();
        ArrayList<Integer> res=new ArrayList<>();
        if(root==null) return res;
        queue.offer(root);
        while(!queue.isEmpty()){
            int len=queue.size();
            while(len>0){
                len--;
                TreeNode node=queue.poll();
                res.add(node.val);
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return res;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值