面试题 16.07. 最大数值

本文旨在对于个人知识的梳理以及知识的分享,如果有不足的地方,欢迎大家在评论区指出


题目描述

编写一个方法,找出两个数字a和b中最大的那一个。不得使用if-else或其他比较运算符。
示例:

输入: a = 1, b = 2
输出: 2
题目链接
题目分析

题目中要求我们不可以使用任何的比较运算,所以自然而然想到可以使用位运算来解决,首先说我个人的思路,题目中数字的范围都在int范围内,首先如果两个数字符号不同,则直接返回正数,如果相同的话,那么int的最高位为31,从最高位开始枚举,谁的最高位先有1,则代表谁越大,这里可能会有一个疑惑就是正数这样比较是ok的,那么负数为什么也行呢,这里就先介绍一个下面也会用到的概念,计算机中的负数是以补码的形式存储的,补码是原码取反之后加1的值,例如9的原码是00001001,而-9的补码为11110111,也就是说如果其中一个负数的高位为1而另一个为0,则它对应的正数的值要小,那么加上负号值就大了,这也就是为什么负数也ok的原因


另外还有一种思路,更偏向于数学方面,对于 M a x ( a , b ) Max(a, b) Max(a,b),它的值其实等于 a + b + a b s ( a − b ) 2 \frac{a + b + abs(a-b)}{2} 2a+b+abs(ab),在代码中,abs函数是含有比较运算的,所以我们可以重写abs,为了防止int溢出,我们统一使用long类型,对于重写的abs函数,思路如下,首先我们要判断当前数字的正负号,在计算机中,最高位存储的是数字的符号,所以x >> 63就可以获得x的符号flag,如果为正数,那么flag=0,如果为负数,那么flag=-1,之后我们取x的绝对值为(x^flag)-flag,这里比较巧妙,我们可以举个例子看一下对不对,首先当x为正数的时候,发现返回的就是x本身,当x为负数的时候,由于和-1异或就相当于每一位都取反,之后再+1,这个操作其实就是补码转原码的操作,也就是对符号取反了


解题代码
解法①:

Java

class Solution {
    public int maximum(int a, int b) {
        if(a>0&&b<0) return a;
        if(a<0&&b>0) return b;
        int k = 31;
        while(k -- >= 0){
            if((a>>k&1)==1&&(b>>k&1)==0) return a;
            if((b>>k&1)==1&&(a>>k&1)==0) return b;
        }
        return a;
    }
}

Python

class Solution:
    def maximum(self, a: int, b: int) -> int:
        if a>0 and b<0:
            return a
        if a<0 and b>0:
            return b
        k = 31
        while k >= 0:
            if ((a>>k&1) == 1 and (b>>k&1) == 0):
                return a
            if ((b>>k&1) == 1 and (a>>k&1) == 0):
                return b
            k -= 1
        return a

解法②:

Java

class Solution {

    private long myAbs(long a){
        int flag = (int)(a>>63);
        return (flag^a)-flag;
    }

    public int maximum(int a, int b) {
        long la = a; long lb = b;
        return (int)((la+lb+myAbs(la-lb))/2);
    }
}

Python

class Solution:
    def maximum(self, a: int, b: int) -> int:
        # 自定义绝对值函数
        def myAbs(a):
            flag = a>>63
            return (flag^a)-flag
        
        return (a+b+myAbs(a-b))//2
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值