[Java实现]剑指offer11-15题_day3

11.二进制中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,就可以进行多少次这样的操作.
(注意:与是不是负数没有关系.每次都是把最右的1计算并清除,这样就只剩下其它的1,并且没有新加的1,所以和是不是负数无关!)

package com.matajie;

/**
 * 11.二进制中1的个数
 * 题目描述
 * 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/
public class NumberOf1 {
    public int NumberOf1(int n) {
         int count = 0;
         while (n != 0){
             count++;
             n = n & (n - 1);
         }
         return count;
    }
}

12.数值的整数次方

题目描述

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

思路:

进入这道题之间我们先了解一下什么是快速幂.
先举个栗子:我们想计算X8 : 我们如果一个一个往上乘需要进行7次运算.
(XX)(XX)(XX)(XX),用这种求法,先进行乘法得X2,再执行三次乘法,这样去计算,则乘法运算执行4次,所以为了快速计算整数幂,我们就会考虑这种思想.

整数快速幂计算XN:

package com.matajie;

/**
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 * 整数快速幂
 * 用X^19举例,19转为二进制 10011;
 * 1 0 0 1 1
 * 
 * 初始: ans = 1, res = X;
 * 
 * 1 : ans = res * ans = X;
 *     res = res * res = X^2;
 * 
 * 1 : ans = res * ans = X^3;
 *     res = res * res = X^4;
 * 
 * 0 : res = res * res = X^8;
 * 
 * 0 : res = res * res = X^16;
 * 
 * 1 : ans = res * ans = X^19;
 *     res = res * res = X^32;
 **/
public class IntegerFastPower {
    int QuickPow(int X, int N){
        int res = X;
        int ans = 1;
        while (N != 0){
            if ((N & 1) != 0){
                ans *= res;
          }
                res *= res;
                N =N>>1;

        }
        return ans;
    }
}


以N = 19为例, 二进制表示为 10011, 二进制从右向左算,但乘出来顺序是X1 * X2 * X16是从左向右的,我们不断地让res *= res,目的就是累乘,以便随时对ans做出贡献, res * res = res2,下一步再乘就是res2 * res2 = res4,同理可得res ->res2 -> res 4 ->res 8 ->res16 -> … 我们发现指数正是2i,我们再看这个例子,X19=X1 * X2 * X16,这三项完美解决,这就是快速幂.

再回来看本题,就很简单了.(注意:int类型abs(INT_MIN)会溢出,所以用long.)

package com.matajie;

/**
 * 12.数值的整数次方
 * 题目描述
 *
 * 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/
public class Power {
    public double Power(double base, int exponent) {
       //int类型abs(INT_MIN)会溢出,所以用long.
        long p = Math.abs((long) exponent);
        double res = 1.0;
        while (p != 0) {
            if((p&1)!=0){
                res *= base;
            }
            base *= base;
            p = p >> 1;
        }
        return exponent<0?1/res:res;
    }
}

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

题目描述

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

思路:(本题我的思路不太好,希望当有大神看到的时候可以指点一下qaq)

思路一:冒泡法:前偶后奇就交换.

package com.matajie;

/**
 * 13.调整数组顺序使奇数位于偶数前面
 * 题目描述
 *
 * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,
 * 使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/
public class ReOrderArray {
    public void reOrderArray(int [] array) {
        int length = array.length;
        for(int i = 0;i<length;i++){
            for(int j = length-1;j>0;j--){
                if(array[j] % 2 == 1 && array[j-1] % 2 == 0){
                    int temp = array[j];
                    array[j] = array[j-1];
                    array[j-1] = temp;
                }
            }
        }
    }
}

思路二:遍历这个数组得到哪些位置应该存奇数,哪些位置应该存偶数,然后再遍历这个数组,遇到奇数则依次放到奇数的位置,遇到偶数则依次放到偶数的位置.

package com.matajie;

/**
 * 13.调整数组顺序使奇数位于偶数前面
 * 题目描述
 *
 * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,
 * 使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/
public class ReOrderArray {
    public void reOrderArray(int [] array) {
       int length = array.length;
       int count = 0;
       for(int i = 0;i<length;i++){
           if(array[i] % 2 != 0){
               count++;
           }
       }
       int[] temp = new int[length];
       int a = 0;
       int b = count;
       for (int j = 0;j<length;j++){
           if(array[j] % 2 == 0){
               temp[b++] = array[j];
           }else {
               temp[a++] = array[j];
           }
       }
       for(int i = 0;i<length;i++){
           array[i] = temp[i];
       }
    }
}

14.链表中倒数第K个节点

题目描述

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

思路(前后指针):

两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指针走(k-1)步,到达第k个节点,然后两个指针同时往后移动,当第一个指针到达末尾时,第二个指针所在位置即为倒数第k个节点.

package com.matajie;

/**
 * 14.链表的倒数第k个节点
 * 题目描述
 * 输入一个链表,输出该链表中倒数第k个结点。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/

public class FindKthToTail {
    public class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode front = head;
        ListNode back = head;
        int i;
        for(i = 0;front != null && i<k;i++){
            front =front.next;
        }
        if(front == null&&i < k){//k>链表长度,返回null
            return null;
        }else if(front == null){
            return head;
        }
        while (front != null) {

            front = front.next;
            back = back.next;
        }
        return back;
    }
}

15.反转链表

package com.matajie;

/**
 * 15.反转链表
 * 题目描述
 * 输入一个链表,反转链表后,输出新链表的表头。
 *
 * 我的程序才不会有bug!
 * author:年仅18岁的天才少年程序员丶mata杰
 **/
public class ReverseList {
    public class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode ReverseList(ListNode head) {
       ListNode result = null;
       ListNode cur = head;
       while (cur != null){
           ListNode next = cur.next;
           //头插
           cur.next = result;
           result =cur;//头插结束
           cur = next;
       }
       return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值