Leetcode题库-两数之和(java语言版)

Leetcode题库-两数之和(java语言版)

  • 第一种方法(for循环嵌套暴力求解)
  • 第二种方法-(map)
  • 第三种方法-终极方法(时间复杂度最低)
  • 第四种方法-先排序在根据位置进行比较
  • 总结

第一种方法(for循环嵌套暴力求解)

根据题目描述:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
这样大多数人的思路都很明确,就是从头遍历数组找到两个数和目标数相同则返回下标
核心代码如下:

   for (int i =0;i

这样确实可以得到结果,但是用时较长,在数组较大时,速度较慢。也就是时间复杂度很高O(n^2),一般在我们的程序中,时间复杂度不能为指数递增。这个方法虽然方便,大多数人都能想到,但是程序不是最优。
程序执行结果:
Leetcode题库-两数之和(java语言版)_第1张图片
提交程序用时

第二种方法-(map)

在第一种方法的基础上,我们不能允许程序中有指数递增的时间复杂度存在,我们得进行优化。怎么优化呢?我们想到java中有Map接口Map接口一一映射. 可以通过键来获取值。给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值。
我们可以将数组中的元素和下标存储到map中,因为map键值对映射的时间复杂度为O(1),这样的话就大大增加了程序的执行速度。
核心代码如下

Map map = new HashMap ();
    for (int i=0;ii){
            System.out.println("序号为:["+i+","+map.get ( shuzhi )+"]");
        }
    }

这样得到的结果用的时间比第一种大大减少,时间复杂度为O(n).这样就对第一种方法进行了优化。提高了效率。
程序执行结果:
Leetcode题库-两数之和(java语言版)_第2张图片
提交程序用时

第三种方法-终极方法(时间复杂度最低)

有人可能会想,第二种方法已经很快了,还有比这个更快的方法吗,当然。
观察第二种方法我们不难发现,他将数组元素存储map与目标元素的具体比较分别进行了处理。我们是不是可以这样想,将他们放到一起,在一个for中进行处理,这样就减少了一个步骤。速度能比第二种方法较快一点。时间复杂度与第二种相同都是O(n).
核心代码如下

for (int i=0;i

代码量相比第二种减少了一些,效率也更高。这个代码将找找两个数的和等于目标数的操作数组元素存储到map中的操作放到了一起,先进行判断,再进行存储。
程序执行结果:Leetcode题库-两数之和(java语言版)_第3张图片
提交程序用时

第四种方法-先排序在根据位置进行比较

第四种方法用时介于第一中和第二种方法之间,时间复杂度是log级别的。
具体思路就是:首先得进行排序(排序方法有好多,冒泡,快速,选择,或者用java自带的排序函数),然后标记排好序数组元素的首位置和末位置,将两者对应元素相加与目标数进行比较,大于目标数则将末尾值向前移动,小于目标数首位置向后移动,直到找到等于目标数的两个元素停止,输出下标。
需要一个存储下标的容器,我选择map。但是map中的key是不能重复的,所以,我们可以想到,让一个key拥有多个value。例如[3,3]数组,存储到map中就是,key:3,value:[0,1]。这样就可以解决遇到数组中重复元素时,map键不能重复的问题。
核心代码如下

  int a=0;
    int b=num.length-1;
    Map> map = new HashMap();
    for (int i = 0; i < num.length; i++) {
        //当不存在键时,正常插入
        if (!map.containsKey ( num[i] )){
            List list1 = new ArrayList <> (  );
            list1.add ( i );
            map.put ( num[i],list1 ); // 将值和下标存入Map
        }
        else {
            //当存在键时,将键对应的值添加道列表里,这样就形成了一个键对应多个值
            List list2 = map.get ( num[i]);
            list2.add ( i );
            map.put ( num[i],list2 );
        }
    }
    System.out.println(map);
    Arrays.sort (num);//用自带的排序函数
    for (int i=0;itarget){
                 b=b-1;
         }
         else if((num[a]+num[b])<><>"+map.get (num[b]));


             }else if(a!=b){
                 System.out.println("序号为:"+map.get (num[a]));
             }
             a=a+1;
         }
    }

程序执行结果:
Leetcode题库-两数之和(java语言版)_第4张图片
这个结果测试了极端问题,数组中有重复元素时,map一个键
对应多个值,可以实现。其他的测试数据也与前三种相同。时间复杂度O(nlogn)级别。

总结

leetcode第一题,两数之和,看似不难,但背后需要考虑很多问题。时间与空间转换问题,数组极端值问题等等。通过这一道题我收获很多,明白了考虑问题得全面。这是本人第一次写博客,本人是一名真正的小白,在此感谢陈学长给我的循循善诱,一步一步的让我明白一个问题应该从哪个角度考虑。本博客由于本人能力有限,肯定有很多的问题,再此大家谅解。
2019-1-15记录

你可能感兴趣的:(编程文章,java,算法,刷题)