1. 2 つの数値の合計 - leetcode

给定一个整数数组 nums 和一个整数目标值 target
请你在该数组中找出 “和”为目标值target的那两个整数
    并返回它们的数组下标
规则:
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

示例1:
输入:nums = [2, 7, 11, 15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回[0, 1] 

示例2:
输入:nums = [3, 2, 4], target = 6
输出:[1,2]

示例3:
输入:nums = [3, 3], target = 6
输出:[0,1]
using System;
using System.Diagnostics;


namespace ConsoleApp2 
{
    internal class Program
    {
        /// <summary>
        /// 思路:
        /// 每个人一个号码,官方表示数字相加为固定数字的一对人可以获得奖励
        /// 官方让找出相加是 target 15的
        /// 小明手中号码是1,其他人分别是小红3,小刚5,小吕7,小紫8
        /// 你是小明,你怎么去找
        /// 方法1:最费力的,就是每个人都去挨个找能与他配对的,小明去找了剩下n-1个人,没找到,小红找剩下的n-2个人,没找到,。。。直到结束
        /// 这样时间复杂度是o(n²)
        
        /// 时间多在哪了?
        /// 那就是没有喊话,小明如果可以喊话,告诉其他人,自己想要的是14号,别人直接能听到,就能直接知道小明能不能配对成功
        ///
        /// 这就需要一个留声机,小明在里面留声,我是x号,我需要target-x号,
        /// 然后小红先去听听有没有别人找自己,没有的话自己也去留声(注意听得过程其实就是查找,如果用数组类型的结构,可以直接在O(1)内找到)
        /// 依次往后
        /// 
        /// 可以选择数组(数组有弊端,就是需要开辟空间过大,不知道应该开辟多少),或者字典等等非链表结构的去存储
        /// </summary>
        /// <param name="nums"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        static int[] TwoSum(int[] nums, int target)
        {
            int[] array = new int[2];
            for (int i = 0; i < nums.Length; i++)
            {
                for (int j = i+1; j < nums.Length; j++)
                {
                    if (nums[i]+nums[j] == target)
                    {
                        array[0] = i;
                        array[1] = j;
                    }
                }
            }
            return array;
        }
        /// 时间多在哪了?
        /// 那就是没有喊话,小明如果可以喊话,告诉其他人,自己想要的是14号,别人直接能听到,就能直接知道小明能不能配对成功
        ///
        /// 这就需要一个留声机,小明在里面留声,我是x号,我需要target-x号,
        /// 然后小红先去听听有没有别人找自己,没有的话自己也去留声(注意听得过程其实就是查找,如果用数组类型的结构,可以直接在O(1)内找到)
        /// 依次往后
        /// 
        /// 可以选择数组(数组有弊端,就是需要开辟空间过大,不知道应该开辟多少),或者字典等等非链表结构的去存储
        
        // 数组(不严谨,主要看下面字典)
        static int[] TwoSum2(int[] nums, int target)
        {
            int[] array = new int[2];
            int[] array2 = new int[100000];
            for (int i = 0; i < 100000; i++)
            {
                array2[i] = 0;
            }
            for (int i = 0; i < nums.Length; i++)
            {
                if (array2[nums[i]] > 0)
                {
                    array[0] = i;
                    array[1] = array2[nums[i]];
                    return array;
                }
                array2[target - nums[i]] = i;
            }
            return array;
        } 
        /// 时间多在哪了?
        /// 那就是没有喊话,小明如果可以喊话,告诉其他人,自己想要的是14号,别人直接能听到,就能直接知道小明能不能配对成功
        ///
        /// 这就需要一个留声机,小明在里面留声,我是x号,我需要target-x号,
        /// 然后小红先去听听有没有别人找自己,没有的话自己也去留声(注意听得过程其实就是查找,如果用数组类型的结构,可以直接在O(1)内找到)
        /// 依次往后
        /// 
        /// 可以选择数组(数组有弊端,就是需要开辟空间过大,不知道应该开辟多少),或者字典等等非链表结构的去存储
        //字典
        static int[] TwoSum3(int[] nums, int target)
        {
            int[] array = new int[2];
            // 留声机
            Dictionary<int, int> dir = new Dictionary<int, int>();
            for (int i = 0; i < nums.Length; i++)
            {
                // 在留声机中听听是否有人找过自己 
                if (dir.ContainsKey(nums[i]))
                {
                    array[0] = i;
                    array[1] = dir[nums[i]];
                    return array;
                }
                // 如果没有任何找过自己,那就把自己要找的和自己的联系方式留进去
                // 并且 因为可能两个人拿的是同一个号码,题目只让找出其中的一份就行,所以在这加入限制,留声机内存在寻找x号的了,就不用再存进去新的了
                // key为自己要找的人,value是自己的联系方式,不能反,反了就无法利用O(1)的特性了
                if (!dir.ContainsKey(target - nums[i]))
                {
                    dir.Add(target - nums[i],i);
                }
            }
            return array;
        }
        static void Main(string[] args)
        {
            int[] array = TwoSum3(new int[] {1,1,1,1,1,4,1,1,1,1,1,7,1,1,1,1,1},11);
            // int[] array = TwoSum3(new int[] {1,1,1,1,3},4);
            foreach (var value in array)
            {
                Console.WriteLine((value));
            }
        }
    }
}

知らせ

配列や辞書などの構造体はアドレス クエリ データに直接アクセスし、クエリ時間は O(1) であるため、クエリを実行する数値を辞書のキーとして使用することが、時間の複雑さを軽減する一般的な方法です。

おすすめ

転載: blog.csdn.net/qq_32175379/article/details/124269095