Algorithm 2-和的线性时间算法
给定一个整数x和一个由N个不同整数组成的排序数组a,设计一个线性时间算法来确定是否存在两个不同的索引i和j,以便a[i]+a[j]==x根据补码进行思考 在列表上迭代,找出每个项目到达X所需的数字。将数字和补码粘贴到哈希中。迭代时,检查数字或其补码是否在哈希中。如果有,请找到 编辑:还有一些时间,一些伪代码Algorithm 2-和的线性时间算法,algorithm,Algorithm,给定一个整数x和一个由N个不同整数组成的排序数组a,设计一个线性时间算法来确定是否存在两个不同的索引i和j,以便a[i]+a[j]==x根据补码进行思考 在列表上迭代,找出每个项目到达X所需的数字。将数字和补码粘贴到哈希中。迭代时,检查数字或其补码是否在哈希中。如果有,请找到 编辑:还有一些时间,一些伪代码 boolean find(int[] array, int x) { HashSet<Integer> s = new HashSet<Integer>();
boolean find(int[] array, int x) {
HashSet<Integer> s = new HashSet<Integer>();
for(int i = 0; i < array.length; i++) {
if (s.contains(array[i]) || s.contains(x-array[i])) {
return true;
}
s.add(array[i]);
s.add(x-array[i]);
}
return false;
}
布尔查找(int[]数组,int x){
HashSet s=新的HashSet();
for(int i=0;i
这是一种
这是我的解决办法。我不知道是不是早就知道了。想象两个变量i和j的函数的3D图:
sum(i,j) = a[i]+a[j]
对于每个i
都有这样的j
,a[i]+a[j]
最接近x
。所有这些(i,j)
对形成最接近x的线。我们只需要沿着这条线走,寻找a[i]+a[j]==x
:
int i = 0;
int j = lower_bound(a.begin(), a.end(), x) - a.begin();
while (j >= 0 && j < a.size() && i < a.size()) {
int sum = a[i]+a[j];
if (sum == x) {
cout << "found: " << i << " " << j << endl;
return;
}
if (sum > x) j--;
else i++;
if (i > j) break;
}
cout << " not found\n";
inti=0;
int j=下限(a.begin(),a.end(),x)-a.begin();
而(j>=0&&j第一次通过搜索第一个值,即>ceil(x/2)。让我们将此值称为L
从L的索引开始,向后搜索,直到找到与和匹配的另一个操作数
它是2*n~O(n)
我们可以扩展到二进制搜索
使用二进制搜索搜索一个元素,这样我们就可以找到L,这样L就是min(a>ceil(x/2)中的元素)
对R执行相同的操作,但现在使用L作为数组中可搜索元素的最大大小
这种方法是2*log(n)。迭代数组并将限定的数字及其索引保存到映射中。该算法的时间复杂度为O(n)
vector twoSum(向量和数字,整数目标){
地图摘要;
矢量结果;
对于(int i=0;i
我只想将差异添加到哈希集
,如下所示:
public static bool Find(int[] array, int toReach)
{
HashSet<int> hashSet = new HashSet<int>();
foreach (int current in array)
{
if (hashSet.Contains(current))
{
return true;
}
hashSet.Add(toReach - current);
}
return false;
}
publicstaticboolfind(int[]数组,int-toReach)
{
HashSet HashSet=新的HashSet();
foreach(数组中的当前整数)
{
if(hashSet.Contains(当前))
{
返回true;
}
Add(toReach-current);
}
返回false;
}
注意:代码是我的,但测试文件不是。此外,哈希函数的这个想法来自网络上的各种阅读
Scala中的一个实现。它使用hashMap和值的自定义(但很简单)映射。我同意它没有使用初始数组的排序性质
散列函数
我通过将每个值除以10000来确定存储桶的大小。这个数字可能会有所不同,这取决于您想要存储桶的大小,根据输入范围可以使其达到最佳
例如,键1负责从1到9的所有整数
对搜索范围的影响
这意味着,对于当前值n,您希望找到补码c,例如n+c=x(x是您试图找到的2-和的元素),只有3个补码可能是:
- -钥匙
- -键+1
- -键-1
假设您的号码位于以下格式的文件中:
0
1
10
10
-10
10000
-10000
10001
9999
-10001
-9999
10000
5000
5000
-5000
-1
1000
2000
-1000
-2000
下面是Scala中的实现
import scala.collection.mutable
import scala.io.Source
object TwoSumRed {
val usage = """
Usage: scala TwoSumRed.scala [filename]
"""
def main(args: Array[String]) {
val carte = createMap(args) match {
case None => return
case Some(m) => m
}
var t: Int = 1
carte.foreach {
case (bucket, values) => {
var toCheck: Array[Long] = Array[Long]()
if (carte.contains(-bucket)) {
toCheck = toCheck ++: carte(-bucket)
}
if (carte.contains(-bucket - 1)) {
toCheck = toCheck ++: carte(-bucket - 1)
}
if (carte.contains(-bucket + 1)) {
toCheck = toCheck ++: carte(-bucket + 1)
}
values.foreach { v =>
toCheck.foreach { c =>
if ((c + v) == t) {
println(s"$c and $v forms a 2-sum for $t")
return
}
}
}
}
}
}
def createMap(args: Array[String]): Option[mutable.HashMap[Int, Array[Long]]] = {
var carte: mutable.HashMap[Int,Array[Long]] = mutable.HashMap[Int,Array[Long]]()
if (args.length == 1) {
val filename = args.toList(0)
val lines: List[Long] = Source.fromFile(filename).getLines().map(_.toLong).toList
lines.foreach { l =>
val idx: Int = math.floor(l / 10000).toInt
if (carte.contains(idx)) {
carte(idx) = carte(idx) :+ l
} else {
carte += (idx -> Array[Long](l))
}
}
Some(carte)
} else {
println(usage)
None
}
}
}
这是一个使用字典数据结构和数字补码的python版本。它具有线性运行时间(顺序为N:O(N)):
int[]b=新的int[N];
对于(int i=0;i cout这里是O(n)时间O(1)空间的线性时间复杂度解
public void twoSum(int[]arr){
如果(arr.length<2)返回;
int max=arr[0]+arr[1];
int biger=Math.max(arr[0],arr[1]);
int较小=数学最小值(arr[0],arr[1]);
int-biggerIndex=0;
int smallerIndex=0;
对于(int i=2;i更小)
{
较小=arr[i];
smallerIndex=i;
}
最大值=较大+较小;
}
}
System.out.println(“最大和为:“+max+”,带索引[“+biggerIndex+”,“+smallerIndex+”]);
}解决方案
- 我们需要数组来存储索引
- 检查数组是否为空或包含的元素是否少于2个
- 定义阵列的起点和终点
- 迭代直到满足条件
- 检查总和是否等于目标。如果是,则获取索引
- 如果不满足条件,则根据总和值向左或向右移动
- 向右移动
- 向左移动
有关更多信息:[
归功于列奥尼德
如果你想试试他的java解决方案
我删除了返回,因此如果数组已排序,但允许重复,它仍然会给出对
static boolean cpp(int[] a, int x) {
int i = 0;
int j = a.length - 1;
while (j >= 0 && j < a.length && i < a.length) {
int sum = a[i] + a[j];
if (sum == x) {
System.out.printf("found %s, %s \n", i, j);
// return true;
}
if (sum > x) j--;
else i++;
if (i > j) break;
}
System.out.println("not found");
return false;
}
静态布尔cpp(int[]a,int x){
int i=0;
int j=a.长度-1;
而(j>=0&&jdef twoSum(N, x):
dict = {}
for i in range(len(N)):
complement = x - N[i]
if complement in dict:
return True
dict[N[i]] = i
return False
# Test
print twoSum([2, 7, 11, 15], 9) # True
print twoSum([2, 7, 11, 15], 3) # False
int[] b = new int[N];
for (int i = 0; i < N; i++)
{
b[i] = x - a[N -1 - i];
}
for (int i = 0, j = 0; i < N && j < N;)
if(a[i] == b[j])
{
cout << "found";
return;
} else if(a[i] < b[j])
i++;
else
j++;
cout << "not found";
public void twoSum(int[] arr){
if(arr.length < 2) return;
int max = arr[0] + arr[1];
int bigger = Math.max(arr[0], arr[1]);
int smaller = Math.min(arr[0], arr[1]);
int biggerIndex = 0;
int smallerIndex = 0;
for(int i = 2 ; i < arr.length ; i++){
if(arr[i] + bigger <= max){ continue;}
else{
if(arr[i] > bigger){
smaller = bigger;
bigger = arr[i];
biggerIndex = i;
}else if(arr[i] > smaller)
{
smaller = arr[i];
smallerIndex = i;
}
max = bigger + smaller;
}
}
System.out.println("Biggest sum is: " + max + "with indices ["+biggerIndex+","+smallerIndex+"]");
static boolean cpp(int[] a, int x) {
int i = 0;
int j = a.length - 1;
while (j >= 0 && j < a.length && i < a.length) {
int sum = a[i] + a[j];
if (sum == x) {
System.out.printf("found %s, %s \n", i, j);
// return true;
}
if (sum > x) j--;
else i++;
if (i > j) break;
}
System.out.println("not found");
return false;
}