【剑指offer@JZ11--JZ20】

JZ11:二进制中1的个数

题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示
解题思路:每次 n & (n-1) 都会使得二进制数据的最右边的一个1变为0,所以有多少个1就会执行循环多少次

public class Solution {
    public int NumberOf1(int n) {
        int count=0;
        while(n!=0){
            count++;
            n=n&(n-1);
        }
        return count;
    }
}

JZ12:数值的整数次方

题目描述:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0
解题思路:调用pow方法,需要特别注意,0的0次方等于1

public class Solution {
    public double Power(double base, int exponent) {
        if(base==0){
            return 0;
        }
        if(base==0&&exponent==0){
            return 1;
        }
        return Math.pow(base,exponent);
  }
}

JZ13:调整整数顺序使奇数位于偶数前面

题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变
解题思路:两个循环从前往后去遍历,遇到奇数偶数就交换

public class Solution {
    public void reOrderArray(int [] array) {
        for(int i=0;i<array.length;i++){
            for(int j=0;j<array.length-1-i;j++){
                if(array[j]%2==0&&array[j+1]%2==1){
                    int temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                }
            }
        }
    }
}

JZ14:链表中倒数第k个节点

解题思路:先统计一下有多少个节点。从前往后遍历到第k个输出就行

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

JZ15:反转链表

题目描述:输入一个链表,反转链表后,输出新链表的表头。
解题思路:从头节点开始,利用改变指向来反转

public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head==null){//当前为空的话直接返回空
            return null;
        }
        ListNode pre=null;
        ListNode next=null;
        while(head!=null){
            next=head.next;//保存next(下面会更新next,所以要保存)
            head.next=pre;//head.next指向pre
            pre=head;
            head=next;//进行下一个反转
        }
        return pre;
    }
}

JZ16:合并两个有序链表

解题思路:定义一个新的链表,根据list1位置的值list2位置的值去,让新的链表去把这两个链表的值按顺序大小依次添加,

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2){
        if(list1==null){//分析链表为空的情况
            return list2;
        }
        if(list2==null){
            return list1;
        }
        ListNode node=new ListNode(0);
        ListNode pr1=list1,pr2=list2;
        ListNode result=node;
        while(pr1!=null&&pr2!=null){//去判断两个val值得大小决定result接下来往哪儿遍历
            if(pr1.val<=pr2.val){
                result.next=pr1;
                result=pr1;
                pr1=pr1.next;
            }else{
                result.next=pr2;
                result=pr2;
                pr2=pr2.next;
            }
        }
        if(pr1!=null)//判断最后剩的是pr1还是pr2的
            result.next=pr1;
        if(pr2!=null)
            result.next=pr2;
        return node.next;
    }
}

JZ17:树的子结构

题目描述:输入两棵二叉树A,B,判断B是不是A的子结构(ps:我们约定空树不是任意一个树的子结构)
解题思路:树的问题一般都是用递归来解决,先找到对应的那个根节点,然后往下递归遍历。

public class Solution {
    public  boolean HasSubtree(TreeNode root1, TreeNode root2) {
        boolean flag= false;
        if (root2!=null&&root1!=null) {//树不为空才能比较
            if(root1.val == root2.val){//找到了root2对应的根节点
                flag= sonTree(root1,root2);//去判断是不是子树
            }
            //如果找不到,就去root的左边找
            if (!flag) {
                flag= HasSubtree(root1.left,root2);
            }
            //如果还找不到,就去root的右边找
            if (!flag) {
                flag=HasSubtree(root1.right,root2);
               }
            }
        return flag;
    }
 
    public  boolean sonTree(TreeNode node1, TreeNode node2) {
        if (node2 == null) {//Tree2为空了,说明节点都对上了
            return true;
        }
        //Tree2还没有遍历完,Tree1却完了。返回false
        if (node1 == null) {//Tree1还没完,Tree1完了,说明没对上
            return false;
        }
        if (node1.val != node2.val) {  //某一个点没对上,也说明不是
                return false;
        }
         
        //如果根节点对应的上,那么就分别去子节点里面匹配
        return sonTree(node1.left,node2.left) &&sonTree(node1.right,node2.right);
    }
}

JZ18:二叉树的镜像

题目描述:就判断是不是这样就行
在这里插入图片描述
解题思路:先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子节点,当交换完所有的非叶子结点的左右子结点之后,就得到了树的镜像

public class Solution {
    public void Mirror(TreeNode root) {
        if(root==null){//空树
            return;
        }
        if(root.right==null&&root.left==null){//说明树只有一个节点
            return;
        }
        TreeNode temp=root.left;//交换它的左右节点
        root.left=root.right;
        root.right=temp;
        if(root.right!=null){//为空时说明找到了递归的出口
            Mirror(root.right);
        }
        if(root.left!=null){
            Mirror(root.left);
        }
    }
}

JZ19:顺时针打印矩阵

题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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 [][] arr) {
        ArrayList<Integer> result = new ArrayList<Integer> ();
        int n = arr.length,m = arr[0].length;
        if(m==0||n==0)
            return result;
        int layers = (Math.min(n,m)-1)/2+1;//这个是圆的层数,不是数组的层数
        for(int i=0;i<layers;i++){
            for(int k = i;k<m-i;k++) {//左至右
                result.add(arr[i][k]);
            }
            for(int j=i+1;j<n-i;j++){//右上至右下
                result.add(arr[j][m-i-1]);
            }
            for(int k=m-i-2;(k>=i)&&(n-i-1!=i);k--){//右至左
                result.add(arr[n-i-1][k]);
            }
            for(int j=n-i-2;(j>i)&&(m-i-1!=i);j--) {//左下至左上
                result.add(arr[j][i]);
            }
        }
        return result;
    }
}

JZ20:包含min函数的栈

题目描述:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。
解题思路:定义两个栈来实现,比如放第一个数字3,stack1正常添加,stack2为空,此时也正常添加,添加第二个数字2,stack1添加,stack2不添加,添加第三个数字1,stack1正常添加,由于(node < stack2.peek()),stack2也添加,最终pop出来的stack2.peek()就是最小的

import java.util.Stack;
public class Solution {
    Stack<Integer> stack1 = new Stack<>(); //创建两个栈 Stack1作为主栈
    Stack<Integer> stack2 = new Stack<>(); //用辅栈来存放最小数据
    public void push(int node) {
        stack1.push(node); //主栈存放数据
        if (stack2.isEmpty()) { //如果辅栈为空,添加该数据。
            stack2.push(node);
        }
        else if (node < stack2.peek()) {//如果新添数据比辅栈最小值还要小,那么辅栈添加该数据
            stack2.push(node);
        }
    }
    public void pop() { //在弹出的时候,如果当前弹出值为最小值,辅栈也进行pop。
        if(stack1.peek()==stack2.peek())
            stack2.pop();
            stack1.pop();
    }
    public int top() {
        return stack1.peek(); //top只是返回栈顶元素,不用进行增删操作。
    }
    public int min() {
        return stack2.peek(); //返回辅栈栈顶元素,栈顶存放的是最小元素。
    }
}

猜你喜欢

转载自blog.csdn.net/chris__x/article/details/106869144