剑指offer_编程题_java版(11-20)

二进制中1的个数

题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

/**方法一大致思路:
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,
那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1
(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
举个例子:
一个二进制数1100,从右边数起第三位是处于最右边的一个1。
减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,
因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所
有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与
运算,从原来整数最右边一个1那一位开始所有位都会变成0。
如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,
会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以
进行多少次这样的操作。
*/
public class Solution {
    //方法一
    //&和&&都可以用作逻辑与的运算符,表示逻辑与(and)
    //&还可以用作位运算符(按照二进制),&&还具有短路的功能
    public int NumberOf1(int n) {
        int num=0;
        while(n!=0){
            n=n&(n-1);
            num++;
        }
        return num;
     }
    //方法二
    public int NumberOf2(int n) {
         String str=Integer.toBinaryString(n);
         char[] c=str.toCharArray();
         int num=0;
         for(int i=0;i<c.length;i++){
             if(c[i]=='1'){
                 num++;
             }
         }
     return num;
     }
}

数值的整数次方

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

保证base和exponent不同时为0

public class Solution {
    public double Power(double base, int exponent) {
       //方法一
       //return Math.pow(base,exponent);
        //方法二
        if(base==0) return base;
        double result=1;//当exponent=0 的时候=1
        int e=exponent>0?exponent:-exponent;
        for(int i=0;i<e;i++){
            result*=base;
        }
        return exponent>0?result:1/result;
    }
}

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

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

public class Solution {
    //借鉴冒泡排序的特点,让偶数不断向右边移动,而冒泡的过程本身
    //也可以保证相对顺序的不变,最后所有的偶数都移动到了右边
    public void reOrderArray(int [] array) {
        for(int i= 0;i<array.length-1;i++){
            for(int j=0;j<array.length-1-i;j++){
                if(array[j]%2==0&&array[j+1]%2==1){
                    int t = array[j];
                    array[j]=array[j+1];
                    array[j+1]=t;
                }
            }
        }
    }
}

链表中倒数第k个结点

题目描述
输入一个链表,输出该链表中倒数第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) {
       if (head == null)   return head;
 
        ListNode node = head;
        int count = 0;
        while (node != null) {
            count++;
            node = node.next;
        }
        if (count < k)  return null;
 
        ListNode p = head;
        for (int i = 0; i < count - k; i++) {
            p = p.next;
        }
        return p;
    }
    //解法二
    public ListNode FindKthToTail1(ListNode head,int k) {
        ListNode p=head;
        ListNode q=head;
        int i=0;
        for(;q!=null;i++){
            if(i>=k){
                p=p.next;
            }
            q=q.next;
        }
        return i<k?null:p;
    }
}

反转链表

题目描述
输入一个链表,反转链表后,输出新链表的表头。

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

合并两个排序的链表

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

/*
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 h = new ListNode(-1);
                ListNode cur = h;
                while(list1 != null && list2 !=null){
                    if(list1.val<=list2.val){
                        cur.next = list1;
                        list1 = list1.next;
                    }else{
                        cur.next = list2;
                        list2 = list2.next;
                    }
                    cur = cur.next;
                }
                if(list1!=null) cur.next = list1;
                if(list2!=null) cur.next = list2;
                return h.next;
     }
}

树的子结构

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

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
 
    public TreeNode(int val) {
        this.val = val;
 
    }
 
}
*/
/**
子结构定义:树A和树B的根结点相等,
并且树A的左子树和树B的左子树相等,树A的右子树和树B的右子树相等

递归函数的功能:判断2个数是否有相同的结构,如果相同,返回true,否则返回false
递归终止条件:
如果树B为空,返回true,此时,不管树A是否为空,都为true
否则,如果树B不为空,但是树A为空,返回false,此时B还没空但A空了,显然false
下一步递归参数:
如果A的根节点和B的根节点不相等,直接返回false
否则,相等,就继续判断A的左子树和B的左子树,A的右子树和B的右子树
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
      if ( root2 == null || root1 == null){
             return false;
         }
         return isSubTree(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
    }
      
    private boolean isSubTree(TreeNode root1, TreeNode root2) {
        if(root2==null) return true;;//子结构已经循环完毕,代表全部匹配
        if(root1==null && root2!=null) return false;  //大树已经循环完毕,并未成功匹配     
        if(root1.val==root2.val){//相等后判断左右孩子
            return isSubTree(root1.left, root2.left) && isSubTree(root1.right, root2.right);
        }
        return false;
    }
}

二叉树的镜像

题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/
6 10
/ \ /
5 7 9 11
镜像二叉树
8
/
10 6
/ \ /
11 9 7 5

/**
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);
    }
}

顺时针打印矩阵

题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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<Integer> ();
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
              return list;
        }
        int row=matrix.length;
       int col=matrix[0].length;
       int left=0,top=0,right=col-1,bottom=row-1;
       while(left<=right&&top<=bottom){
           //从左向右
           for(int i=left;i<=right;i++){
               list.add(matrix[top][i]);
           }
           //从上到下(从下一行开始向下走)
           for(int j=top+1;j<=bottom;j++){
               list.add(matrix[j][right]);
           }
           //从右到左
           if(top!=bottom){
               for(int k=right-1;k>=left;k--){
                   list.add(matrix[bottom][k]);
               }
           }
           //从下到上
           if(left!=right){
               for(int l=bottom-1;l>top;l--){
                   list.add(matrix[l][left]);
               }
           }
             
           //下一个正方形矩阵
           top++;left++;right--;bottom--;
             
       }
        return list; 
   }
        
}

包含min函数的栈

题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。

import java.util.Stack;

public class Solution {
    public static Stack<Integer> totalStack=new Stack<Integer>();
     public static Stack<Integer> minStack=new Stack<Integer>();
    
    public void push(int node) {
        totalStack.push(node);
        if(minStack.empty()==true ||node<=minStack.peek()){
            minStack.push(node);
        }else if(node>minStack.peek()){
            minStack.push(minStack.peek());
        }
    }
    
    public void pop() {
        totalStack.pop();
        minStack.pop();
    }
    
    public int top() {
        return totalStack.peek();
    }
    
    public int min() {
        return minStack.peek();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值