Java twoSum算法:如何改进?

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;

我想做一个算法,发现了这个问题

给定一个整数数组,找到两个数字,使它们相加为一个特定的目标数字

函数twoSum应该返回两个数字的索引,以便它们相加到目标,其中index1必须小于index2。请注意,您返回的答案(index1和index2)不是以零为基础的

您可以假设每个输入都有一个解决方案

输入:数字={2,7,11,15},目标=9

输出:index1=1,index2=2

我的解是O(n^2)。我想知道是否有更好的方法?像O(n)或O(nlogn)

导入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)
    memory

    O(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};
        }