Java twoSum算法:如何改进?
我想做一个算法,发现了这个问题 给定一个整数数组,找到两个数字,使它们相加为一个特定的目标数字 函数twoSum应该返回两个数字的索引,以便它们相加到目标,其中index1必须小于index2。请注意,您返回的答案(index1和index2)不是以零为基础的 您可以假设每个输入都有一个解决方案 输入:数字={2,7,11,15},目标=9 输出:index1=1,index2=2 我的解是O(n^2)。我想知道是否有更好的方法?像O(n)或O(nlogn)Java twoSum算法:如何改进?,java,Java,我想做一个算法,发现了这个问题 给定一个整数数组,找到两个数字,使它们相加为一个特定的目标数字 函数twoSum应该返回两个数字的索引,以便它们相加到目标,其中index1必须小于index2。请注意,您返回的答案(index1和index2)不是以零为基础的 您可以假设每个输入都有一个解决方案 输入:数字={2,7,11,15},目标=9 输出:index1=1,index2=2 我的解是O(n^2)。我想知道是否有更好的方法?像O(n)或O(nlogn) 导入java.util.array;
导入java.util.array;
公共类返回索引{
公共int[]twoSum(int[]数字,int目标){
int tail=number.length-1;
int[]n=新的int[2];
对于(int i=0;i我将这样处理:
从较小的值到较低的值对数组进行排序
按现有方式在阵列上循环,但在任何时候都要尽早退出循环
target对数组排序。使两个指针分别指向第一个和最后一个(x和x)。在循环中运行此操作:
if (a[X]+a[x] > N) then X--
else if (a[X]+a[x] < N) then x++
else if (a[X]+a[x] == N) then found.
if (x > X) then no numbers exist.
如果(a[X]+a[X]>N)那么X--
否则如果(a[X]+a[X]x),则不存在数字。
O(nlogn)
time,O(1)
memoryO(n log n)
time,O(1)
memory(不计算列表):
首先,对列表进行排序。这应该需要O(n log n)
时间,就像大多数排序函数一样
遍历列表,在外循环中应该花费O(n)
时间。此时,您可以在已排序的子列表中对最接近的匹配整数进行二进制搜索,这应该花费O(log n)
时间。此阶段应该花费O(n log n)
总时间
编辑:查看下面Max的答案。它仍然是O(n log n)时间和O(1)内存,但他通过从列表的每一端移动一个指针来避免二进制搜索
O(n)
时间,O(n)
内存:
构建一个哈希表,其中应该有O(1)
插入和O(1)
包含。然后,在O(n)
外循环中,对于每个数字i
,检查total-i
是否在哈希表中。如果没有,则添加它;如果是,则获得两个数字
无论哪种方式,都需要对数组进行额外的扫描以获得索引,但这没有问题——只需要O(n)
time。如果您想避免它,您可以根据需要将原始索引保留在排序列表或哈希表中,但这样会占用内存而不是时间。下面您可以找到一个解决方案,其中两个数字可以在O(n log n)
time中找到:
1- Sort the numbers in ascending (or descending) order // O(n log n)
2- Compute diff = target - item for each item // O(n)
3- For each calculated diff, look up the calculated value in the sorted items
using the Binary search algorithm // O(n log n)
一个完整的Java工作实现:
import java.util.ArrayList;
public class NumbersFinder {
class Item{
private int value;
private int index;
public Item(int value, int index){
this.value = value;
this.index = index;
}
public int getValue(){
return value;
}
public int getIndex(){
return index;
}
}
public ArrayList<Item> find(int[] values, int target){
ArrayList<Item> items = new ArrayList<Item>();
for(int i = 0; i < values.length; i++)
items.add(new Item(values[i], i));
items = quicksort(items);
ArrayList<Integer> diffs = computeDiffs(items, target);
Item item1 = null;
Item item2 = null;
boolean found = false;
for(int i = 0; i < diffs.get(i) && !found; i++){
item1 = items.get(i);
item2 = searchSortedItems(items, diffs.get(i), 0, items.size());
found = item2 != null;
}
if(found){
ArrayList<Item> result = new ArrayList<Item>();
result.add(item1);
result.add(item2);
return result;
}
else
return null;
}
// find "value" in the sorted array of "items" using Binary search in O(log n)
private Item searchSortedItems(ArrayList<Item> items, Integer value, int lower, int upper) {
if(lower > upper)
return null;
int middle = (lower + upper)/2;
Item middleItem = items.get(middle);
if(middleItem.getValue() == value)
return middleItem;
else if(middleItem.getValue() < value)
return searchSortedItems(items, value, middle+1, upper);
else
return searchSortedItems(items, value, lower, middle-1);
}
// Simply calculates difference between the target value and each item in the array; O(n)
private ArrayList<Integer> computeDiffs(ArrayList<Item> items, int target) {
ArrayList<Integer> diffs = new ArrayList<Integer>();
for(int i = 0; i < items.size(); i++)
diffs.add(target - items.get(i).getValue());
return diffs;
}
// Sorts items using QuickSort algorithm in O(n Log n)
private ArrayList<Item> quicksort(ArrayList<Item> items) {
if (items.size() <= 1)
return items;
int pivot = items.size() / 2;
ArrayList<Item> lesser = new ArrayList<Item>();
ArrayList<Item> greater = new ArrayList<Item>();
int sameAsPivot = 0;
for (Item item : items) {
if (item.getValue() > items.get(pivot).getValue())
greater.add(item);
else if (item.getValue() < items.get(pivot).getValue())
lesser.add(item);
else
sameAsPivot++;
}
lesser = quicksort(lesser);
for (int i = 0; i < sameAsPivot; i++)
lesser.add(items.get(pivot));
greater = quicksort(greater);
ArrayList<Item> sorted = new ArrayList<Item>();
for (Item item : lesser)
sorted.add(item);
for (Item item: greater)
sorted.add(item);
return sorted;
}
public static void main(String[] args){
int[] s = {150,24,79,50,88,345,3};
int value = 200;
NumbersFinder finder = new NumbersFinder();
ArrayList<Item> numbers = finder.find(s, value);
if(numbers != null){
System.out.println("First Number Found = " + numbers.get(0).getValue() + " ; Index = " + + numbers.get(0).getIndex());
System.out.println("Second Number Found = " + numbers.get(1).getValue() + " ; Index = " + + numbers.get(1).getIndex());
}
else{
System.out.println("No such two numbers found in the array!");
}
}
}
python中的单行解决方案:
class Solution(object):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
def twoSum(self, nums, target):
x = [[i, nums.index(target-j)] for i,j in enumerate(nums) if nums.count(target-j) > 0 and nums.index(target-j)!=i]
return x.pop()
这是我的带有O(nlog(n))的cpp解决方案:
向量二和(向量和数字,整数目标){
矢量结果;
向量数_dup=向量(数);
排序(数字重复开始(),数字重复结束());
int left=0,right=numbers\u dup.size()-1;
while(左目标){
对--;
}
否则{
左++;
}
}
}
查看我的博客,了解详细的解释。
以下是在java中使用HashMap并对数组进行两次遍历的答案。假设数组中没有重复的元素,并且只存在一个解决方案
import java.util.HashMap;
public class TwoSum {
int[] index = new int[2];
public int[] twoSum(int[] nums, int target)
{
int length = nums.length;
//initialize return values assuming that pair for the given target
//doesn't exist
index[0]=-1;
index[1]=-1;
//sanity check
if(length<1) return index;
HashMap<Integer, Integer> numHash = new HashMap<>(length);
//get the values from array into HashMap assuming that there aren't duplicate values
for(int i=0; i<length;i++)
{
numHash.put(nums[i],i);
}
//check for the value in the array and the difference between target and it. Assume that only
//one such pair exists
for(int i=0;i<length;i++)
{
int val1 = nums[i];
int val2=target-val1;
//make sure that it doesn't return the index of the first number in the pait you are searching for
if( numHash.containsKey(val2) && numHash.get(val2)!=i){
index[0]=i;
index[1] =numHash.get(target-nums[i]);
break;
}
}
return index;
}
}
import java.util.HashMap;
公共类二和{
int[]索引=新的int[2];
公共int[]twoSum(int[]nums,int目标)
{
int length=nums.length;
//初始化返回值,假定给定目标的该对
//不存在
索引[0]=-1;
指数[1]=-1;
//健康检查
if(长度公共静态int[]twoSum(int[]nums,int目标){
int[]resultarray=新int[2];
对于(inti=0;i这是我的python解决方案
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
copy_dict = {}
for pos in range(0, len(nums)):
if nums[pos] not in copy_dict.keys():
copy_dict[nums[pos]] = [pos]
else:
copy_dict[nums[pos]].append(pos)
def get_sum_indexes(sorted_array, target):
right_pointer = len(sorted_array) - 1
left_pointer = 0
while left_pointer < len(sorted_array) or right_pointer > 0:
if sorted_array[right_pointer] + sorted_array[left_pointer] == target:
return [sorted_array[left_pointer], sorted_array[right_pointer]]
elif sorted_array[right_pointer] + sorted_array[left_pointer] > target:
right_pointer -= 1
elif sorted_array[right_pointer] + sorted_array[left_pointer] < target:
left_pointer += 1
return None
sum_numbers = get_sum_indexes(sorted(nums), target)
if len(copy_dict[sum_numbers[0]]) == 1:
answer_1 = copy_dict[sum_numbers[0]][0]
else:
answer_1 = copy_dict[sum_numbers[0]][0]
if len(copy_dict[sum_numbers[1]]) == 1:
answer_2 = copy_dict[sum_numbers[1]][0]
else:
answer_2 = copy_dict[sum_numbers[1]][1]
return sorted([answer_1, answer_2])
print(Solution().twoSum(nums=[-1, -2, -3, -4, -5], target=-8))
print(Solution().twoSum(nums=[-3, -3], target=-6))
类解决方案:
def twoSum(自身、nums、目标):
"""
:type nums:List[int]
:类型目标:int
:rtype:List[int]
"""
复制_dict={}
对于范围(0,len(nums))内的位置:
如果nums[pos]不在副本目录键()中:
抄写[nums[pos]=[pos]
其他:
抄写[nums[pos]]。追加(pos)
def get_sum_索引(排序数组、目标):
右指针=len(排序数组)-1
左指针=0
当左\u指针0时:
如果排序数组[右指针]+排序数组[左指针]==目标:
返回[排序数组[左指针]、排序数组[右指针]]
elif排序数组[右指针]+排序数组[左指针]>目标:
右_指针-=1
elif排序数组[右指针]+排序数组[左指针]<目标:
左指针+=1
一无所获
求和编号=获取求和索引(已排序(nums),目标)
如果len(复制记录[和数值[0]])==1:
答案1=抄写[sum\u number[0][0]
其他:
答案1=抄写[sum\u number[0][0]
如果len(复制记录[和数[1]])==1:
答案2=抄写[sum_number[1][0]
其他:
答案2=抄写[sum\u number[1][1]
返回已排序([答案1,答案2])
打印(Solution().twoSum(nums=[-1,-2,-3,-4,-5],target=-8))
打印(Solution().twoSum(nums=[-3,-3],target=-6))
按非递减顺序对列表排序。这需要O(nlogn)
时间复杂度
找到两个数字,这可以在O(n)
时间内完成
找到两个数字的两个索引,这可以在O(n)
时间内完成
总体复杂性为
vector<int> two_sum(vector<int> &numbers, int target) {
vector<int> result;
vector<int> numbers_dup = vector<int>(numbers);
sort(numbers_dup.begin(), numbers_dup.end());
int left = 0, right = numbers_dup.size() - 1;
while(left <= right) {
int sum = numbers_dup[left] + numbers_dup[right];
if(sum == target) {
//find the idex of numbers_dup[left] and numbers_dup[right]
for(int i = 0; i < numbers.size(); i++) {
if(numbers[i] == numbers_dup[left] || numbers[i] == numbers_dup[right]) {
result.push_back(i);
}
if(result.size() == 2) {
return result;
}
}
}
else if(sum > target) {
right--;
}
else {
left++;
}
}
}
import java.util.HashMap;
public class TwoSum {
int[] index = new int[2];
public int[] twoSum(int[] nums, int target)
{
int length = nums.length;
//initialize return values assuming that pair for the given target
//doesn't exist
index[0]=-1;
index[1]=-1;
//sanity check
if(length<1) return index;
HashMap<Integer, Integer> numHash = new HashMap<>(length);
//get the values from array into HashMap assuming that there aren't duplicate values
for(int i=0; i<length;i++)
{
numHash.put(nums[i],i);
}
//check for the value in the array and the difference between target and it. Assume that only
//one such pair exists
for(int i=0;i<length;i++)
{
int val1 = nums[i];
int val2=target-val1;
//make sure that it doesn't return the index of the first number in the pait you are searching for
if( numHash.containsKey(val2) && numHash.get(val2)!=i){
index[0]=i;
index[1] =numHash.get(target-nums[i]);
break;
}
}
return index;
}
}
public static int[] twoSum(int[] nums, int target) {
int []resultarray=new int[2];
for (int i=0;i<nums.length-1;i++){
for(int k=1;k<nums.length;k++)
{
if(target==nums[i]+nums[k])
{
resultarray[0]=nums[i];
resultarray[1]=nums[k];
}
}
}
return resultarray;
}
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
copy_dict = {}
for pos in range(0, len(nums)):
if nums[pos] not in copy_dict.keys():
copy_dict[nums[pos]] = [pos]
else:
copy_dict[nums[pos]].append(pos)
def get_sum_indexes(sorted_array, target):
right_pointer = len(sorted_array) - 1
left_pointer = 0
while left_pointer < len(sorted_array) or right_pointer > 0:
if sorted_array[right_pointer] + sorted_array[left_pointer] == target:
return [sorted_array[left_pointer], sorted_array[right_pointer]]
elif sorted_array[right_pointer] + sorted_array[left_pointer] > target:
right_pointer -= 1
elif sorted_array[right_pointer] + sorted_array[left_pointer] < target:
left_pointer += 1
return None
sum_numbers = get_sum_indexes(sorted(nums), target)
if len(copy_dict[sum_numbers[0]]) == 1:
answer_1 = copy_dict[sum_numbers[0]][0]
else:
answer_1 = copy_dict[sum_numbers[0]][0]
if len(copy_dict[sum_numbers[1]]) == 1:
answer_2 = copy_dict[sum_numbers[1]][0]
else:
answer_2 = copy_dict[sum_numbers[1]][1]
return sorted([answer_1, answer_2])
print(Solution().twoSum(nums=[-1, -2, -3, -4, -5], target=-8))
print(Solution().twoSum(nums=[-3, -3], target=-6))
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
p = nums[:]
p.sort() #sorting in -> O(nlogn)
r = len(nums)-1
l =0
#find the indices -> O(n)
for i in range(len(nums)):
if(p[l] + p[r]<target):
l += 1
elif (p[l] + p[r]>target):
r -=1
else :
first_num = p[l]
second_num = p[r]
#find the indices of the numbers -> O(n)
for i in range(len(nums)):
if(nums[i]==first_num):
first_index = i
elif (nums[i]==second_num):
second_index = i
return [first_index,second_index]
import UIKit
class Solution{
func twoSum(_ nums: [Int], _ target: Int) -> [Int]{
var finalArray = [Int]()
var newDictionary = [Int:Int]()
for i in 0..<nums.count{
let complement = target - nums[i]
if newDictionary[complement] != nil && newDictionary[complement] != i{
finalArray.append(newDictionary[complement]!)
finalArray.append(i)
return finalArray
}
newDictionary[nums[i]] = i
}
return []
}
}
func main(){
let solution = Solution()
print("All Good" ,solution.twoSum([1, 3, 4 , 5], 6))
}
main()
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> my_map;
for ( int i = 0 ; i < nums.size(); i++ ){
if(my_map.find(target - nums[i]) != my_map.end()){
return vector<int> {my_map[target - nums[i]], i};
}
my_map[nums[i]] = i ;
}
}
};
public static void main(String args[]) {
int[] array = {150,24,79,50,88,345,3};
int sum = 200;
Map<Integer,Integer> table = new HashMap<>();
StringBuilder builder = new StringBuilder();
for(int i=0;i<array.length;i++){
int key = sum - array[i];
if(table.containsKey(key)){
builder.append("index1=").append(table.get(key)).
append(" index2=").append(i);
}else{
table.put(array[i],i);
}
}
System.out.println(builder);
}
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] resultarray=new int[2];
for (int i=0;i<nums.length-1;i++){
for(int k=i+1;k<nums.length;k++)
{
if(target==nums[i]+nums[k])
{
resultarray[0]=i;
resultarray[1]=k;
}
}
}
return resultarray;
}
}
def twoSum(nums, target):
output=[]
arr=sorted(nums)
x=0
y=-1
X=len(nums)-1
while x<X:
if (arr[X]+arr[x] > target):
X-=1
elif (arr[X]+arr[x] < target):
x+=1
elif (arr[X]+arr[x] == target):
#print("Found",arr[X],arr[x])
num1=arr[x]
num2=arr[X]
x+=1
X-=1
for i in range(len(nums)):
if num1 == nums[i] and y==-1:
index1=i
y=i
elif num2 == nums[i]:
index2=i
return [index1, index2]
print(twoSum([3,2,4], 6)) # [1,2]
print(twoSum([3,3], 6)) # [0,1]
public int[] twoSum(int[] numbers, int target) {
int[] arr = new int[2]; // to store result
int sum=0;
int start_pointer=0;
int end_pointer = (numbers.length)-1;
while(start_pointer<=end_pointer){
sum=numbers[start_pointer]+numbers[end_pointer];
if(sum>target)
end_pointer-=1;
else if(sum<target)
start_pointer+=1;
else{
arr[0]=start_pointer;
arr[1]=end_pointer;
break;
}
}
return arr;
}
public class ReturnIndicesOfElementsAddToSum {
public static void main(String[] args) {
int[] nums = {2, 7, 11, 15};
int target = 18;
if(!getIndices(nums,target)) {
System.out.println("No such numbers found");
}
}
static boolean getIndices(int[] nums, int target) {
Map<Integer,Integer> indexMap = new HashMap<>();
boolean numFound = false;
for(int i=0;i<nums.length;i++) {
int temp = target - nums[i];
indexMap.put(nums[i], i);
if(indexMap.containsKey(temp)) {
System.out.printf("%d and %d adds upto the target value and indices are %d and %d"
, nums[i], temp, i, indexMap.get(temp));
numFound = true;
}
}
return numFound;
}
public int[] twoSum(int[] nums, int target) {
int [] resultIndex = null;
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
resultIndex = new int[2];
resultIndex[0]=map.get(temp);
resultIndex[1]=i;
}else{
map.put(nums[i],i);
}
}
return resultIndex;
}
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; i++){
if (nums[i] + nums[i+1] == target)
return new int[] {i, i+1};
}
return null;
}
public int[] findSumMatched(int[] numbers, int target) {
Map<Integer, Integer> mapOfNumbers = new HashMap<Integer, Integer>();
for (int i = 0; i<numbers.length; i++) {
int secondNumber = target - numbers[i];
if (mapOfNumbers.get(secondNumber) != null){
return new int[] {mapOfNumbers.get(secondNumber), i};
}
mapOfNumbers.put(numbers[i], i);
}
throw new IllegalArgumentException();
}
public int[] twoSums(int[] unsortedNum, int target) {
int[] nums = Arrays.copyOf(unsortedNum, unsortedNum.length);
Arrays.sort(nums);
boolean isResultFound = false;
int start = 0;
int end = nums.length-1;
while(!(start > end)) {
if(nums[start]+nums[end] > target){
end--;
} else if (nums[start]+nums[end] < target){
start++;
} else if(nums[start] + nums[end] == target){
isResultFound = true;
break;
}
}
if(isResultFound){
int s = -1;
int e = -1;
for(int i = 0; i< unsortedNum.length; i++){
if(s != -1 && e != -1){
break;
}
if(s == -1 && unsortedNum[i] == nums[start]){
s = i;
} else if(e == -1 && unsortedNum[i] == nums[end]) {
e = i;
}
}
return new int[] {s,e};
}
// for element not found
return new int[]{-1,-1};
}