`

Algorithm之3sum closest及负数在Java中的表示

阅读更多
由一道算法题想到的

1、16. 3Sum Closest


Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).


代码:


import java.util.Arrays;

public class Solution {
    public int threeSumClosest(int[] num, int target) {
        int min = num[0] + num[1] + num[num.length -1];
        Arrays.sort(num);
        for(int i = 0; i < num.length -2; i++){
            int lo = i + 1, hi = num.length - 1;
            while(lo < hi){
                int sum = num[i] + num[lo] + num[hi];
                if(Math.abs(sum - target) < Math.abs(min - target))
                    min = sum;
                if(sum >= target) hi--;
                else lo++;
            }
        }
        return min;
    }
}




时间复杂度为 O(n^2)
为了加快运算效率,我想保存前一个的状态值,记为: preDelta
如果当前 delta 与 preDelta 的符号相同,且 delta 比 preDelta 的绝对值大,
则 break;

但是,在使用异或运算符( preDelta^delta )时,总是得不到想要的结果。
于是回查了一下负数在Java中是如何表示的。又回顾了一下基础知识。

——————————————————————————————————————

引用

什么是2的补码?

它是一种数值的转换方法,要分二步完成:
第一步,每一个二进制位都取相反值,0变成1,1变成0。比如,00001000的相反值就是11110111。
第二步,将上一步得到的值加1。11110111就变成11111000。
所以,00001000的2的补码就是11111000。也就是说,-8在计算机(8位机)中就是用11111000表示。
不知道你怎么看,反正我觉得很奇怪,为什么要采用这么麻烦的方式表示负数,更直觉的方式难道不好吗?


2的补码的好处

首先,要明确一点。计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。
2的补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。
还是以-8作为例子。
假定有两种表示方法。一种是直觉表示法,即10001000;另一种是2的补码表示法,即11111000。请问哪一种表示法在加法运算中更方便?
随便写一个计算式,16 + (-8) = ?
16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:
 00010000
+10001000
---------
 10011000
可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电路。
现在,再来看2的补码表示法。
 00010000
+11111000
---------
100001000
可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。


——————————————————————————————————————


所有的数在Java中都是以其二进制的补码形式存放的。

正数的补码是其自身
负数的补码是:

    负数的绝对值按位取反后 + 1


可以看到:(-0)

/*

在做减法的情况下:


        00000000
    =
        11111111

    +   00000001

---------------------------------------

       100000000

舍掉最高位的溢出,结果还是 0


因为是做减法(加一个负数),如果不够减需要借 1 位。
所以把负数拆分成: 绝对值取反 + 1 这种形式来表示。
把这种表示方式称为:负数的二进制表示法的补码。简称:二进制补码

得到的结果就是代表正数的负值——负数。
然后就可以对负值进行加法运算了。
奇怪的是,这样做加法运算,居然就是正确的。





下面的步骤可以实现:正数 + 负的正数 = 0

1、正数 + 正数各位取反 = 最大值(所有位为 1) 

2、(所有位为 1) + 1 = 0 (舍去溢出位)

--------------------------------------------------

综合起来:

 正数 + 正数各位取反 + 1 = 0

 正数 + (正数各位取反 + 1) = 0

 正数 + (补码) = 0

 正数 + (负数) = 0


--------------------------------------------------

上面只是 正数 + 负数 ,(两数绝对值相等)
还有 大正数 + 负小正数,
还有 负数 + 负数 的情况,不在此证明。

*/



这种表示法可以使计算器只用加法一种电路就可以完成加减乘除四种运算。
(除法是减法,乘法是加法)














引用:

https://leetcode.com/problems/3sum-closest/

http://www.ruanyifeng.com/blog/2009/08/twos_complement.html


-



分享到:
评论

相关推荐

    algorithm-essentials-java

    根据提供的文件信息,“algorithm-essentials-java”似乎是一份关于Java编程语言中算法实现的文档。下面将基于文档中提到的各个部分来详细介绍其中涉及的关键知识点。 ### 引言 在计算机科学领域,算法是解决问题...

    java 银行家算法 algorithm

    在这个Java实现的银行家算法中,我们关注以下几个核心知识点: 1. **资源与需求**:在银行家算法中,系统中的资源被抽象为不同的类型,每种类型有固定的数量。每个进程都有对这些资源的需求,这些需求在进程启动时...

    HungarianAlgorithm.java

    使用java语言实现匈牙利算法。可实现任务最优分配,以及旅行商问题

    JavaAlgorithm.zip

    Java 算法

    DS and Algorithm Ananlysis in Java

    《DS和Algorithm Analysis in Java》是一门针对数据结构与算法分析的课程,主要使用Java语言进行教学。课程的目标是帮助学生理解和分析不同数据结构和算法的时间复杂度与空间复杂度,以便于在实际问题中有效地应用。...

    Java+algorithm.rar_ Java algorit_Algorithm JAVA_algorithm_java

    Java算法大全是一个集合了多种Java实现的算法资源,旨在帮助开发者深入理解和掌握算法。这个压缩包包含了一些关键的算法解释和实例,对于学习和提升Java编程能力,特别是算法设计与分析方面,非常有帮助。 首先,...

    加密解密算法-java 实现(algorithm.rar)

    以下是对标题"加密解密算法-java 实现(algorithm.rar)"和描述中提及的几种算法的详细阐述: 首先,RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,广泛应用于数字签名和安全网络通信。它基于两个大素数的乘积...

    Sum-Product Algorithm:Sum-Product Algorithm应用于HMM-matlab开发

    **Sum-Product算法详解及其在HMM中的应用** Sum-Product算法,又称为消息传递算法,是概率图模型(如马尔可夫随机场或贝叶斯网络)中的一种求解最大似然估计或最优化问题的有效方法。该算法通过在图模型中传播消息...

    algorithm蚂蚁群算法平均Java负载率实现_java

    3. **Java实现**:在Java中,可以创建一个蚁群类,每个实例代表一只蚂蚁。蚂蚁类需要维护当前路径、路径成本等信息。同时,还需要一个环境类来存储所有路径的信息素浓度和启发式信息。每次迭代时,蚂蚁会根据规则...

    Algorithm-java-string-similarity.zip

    Algorithm-java-string-similarity.zip,各种字符串相似度和距离算法的实现:levenshtein、jaro winkler、n-gram、q-gram、jaccard索引、最长公共子序列编辑距离、余弦相似度……,算法是为计算机程序高效、彻底地完成...

    algorithm-essentials-java.zip_Z75_algorithm

    总的来说,"algorithm-essentials-java.zip_Z75_algorithm"这份资源是Java开发者不可多得的学习资料,它将理论与实践相结合,深入浅出地介绍了算法和数据结构在Java编程中的应用,无论你是正在准备面试,还是在工作...

    AlgorithmGossip 常用算法C/java实现

    在C和Java这两种广泛使用的编程语言中实现算法,使得这些资源具有了广泛的适用性。 C语言是一种底层、高效的编程语言,适合编写系统软件和高性能的应用程序。它的算法实现通常更为简洁,运行速度快,但需要对内存...

    3DES加密java实现

    在Java中,我们可以使用`javax.crypto`包中的`Cipher`类来实现3DES加密和解密。首先,我们需要创建一个`SecretKeySpec`对象,用于存储我们的密钥。密钥长度可以是128位(16字节),但3DES实际只使用其中的112位或168...

    Algorithm-algorithm.zip

    在"Algorithm-algorithm.zip"这个压缩包中,我们很可能找到了一个关于算法学习的资源库,尤其是通过"algorithm-master"这个子文件名,我们可以推测这可能是一个关于算法的开源项目或者教程的主目录。接下来,我们将...

    Data Structures and Algorithm Analysis in Java, 3 edition

    标题中的知识点主要包括“数据结构”和“算法分析”两个核心概念,并指出这两者是在Java语言环境下进行讨论的。接下来我将分别解释这些概念。 1. 数据结构 数据结构是计算机存储、组织数据的方式,它旨在以更有效的...

    java.lang.RuntimeException: Unsupported algorithm: HmacSHA1解决方法

    java.lang.RuntimeException: Unsupported algorithm: HmacSHA1 解决方法,阿里云

    md5sum-code_md5sum_md5sum工具_

    总的来说,`md5sum`工具是Linux系统中不可或缺的一部分,它在数据校验、文件完整性验证等方面发挥着重要作用。通过分析和理解其源代码,我们可以深入理解MD5算法的实现以及如何在不同环境中应用。同时,`makefile`的...

Global site tag (gtag.js) - Google Analytics