LeetCode 中有关数组的题目(JAVA代码实现)

 1.两数之和

作为力扣的第一题,我估计很多新手在这里就被劝退了,但其实这道题不难,我们用map存储我们找到的目标整数,当循环结束之后,如果找到,就返回找到的两个整数的数组,如果没找到,直接返回一个空数组。

class Solution{
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> hashtable =new HashMap<Integer,Integer>();
        for(int i =0; i<nums.length;i++){
            if(hashtable.containsKey(target -nums[i])){
                return new int[]{hashtable.get(target-nums[i]),i};                
            }
            hashtable.put(nums[i],i);//将找到的整数值和索引存在hash表中
        }
        return new int[0];//返回一个空数组

    }
}

 运行数据:

 2.两数相加

 

 这道题如果用正常的思路来想的话,那就是先把这两个链表进行翻转,然后将反转后的链表各结点上的值进行相加等到sum,最后把这个sum再进行反转,把这个反转的值再转换成单个值存储到链表的节点上。

但是这样子就很麻烦,而且实现起来也不简单,我们可以用进位制来实现这个算法,满10进1,否则为0,这样子不断向后移动存储相加的值,这样子实现起来是不是就简单的多。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //设置两个链表的头结点,并进行初始
        ListNode head =null,tail=null;
        int carry =0;
        //遍历两个列表,直到有个链表遍历完
        while(l1!=null||l2!=null){
            //判断l1和l2是否为空,如果不为空,那么就获取当前的l1和l2的值
            int n1 =l1!=null?l1.val:0;
            int n2 =l2!=null?l2.val:0;
            //将两个链表的值以及进位制进行相加
            int sum =n1+n2+carry;
            //如果为空,那么创建新的链表头和链表尾
            if(head==null){
                //创建新的节点,并设置其值的和为当前的个位数。同时设置新链表的头和尾都指向这个节点
                head =tail =new ListNode(sum%10);
            }else{
                //在尾节点后面创建一个新的节点,并将当前和为个位数作为节点的值
                tail.next=new ListNode(sum%10);
                //更新尾部节点,使其指向新创建的节点
                tail =tail.next;
                
            }
            carry =sum/10;
            //计算当前的进位,即当前的和的十位数
            if(l1!=null){
                l1 =l1.next;
                //如果l1不为空,则移动到下一个节点
            }
            if(l2!=null){
                l2 =l2.next;
                //如果l2不为空,则移动到下一个节点
            }
        }
        //如果还有剩余的进位值,那么将其添加到链表的尾部
        if(carry>0){
            tail.next =new ListNode(carry);
        }
        //返回新的链表的头节点。这个新链表表示两个输入数字的和
        return head;

    }
}

3.无重复字符的最大子串

 这道题的思路还是简单的,首先我们需要两个指针,一个end用于不断向后获取s字符串中的字符,并将其存入map中,当end将要存入下一个字符时,判断map中是否有相同的字符,如果存在,就将strat更新为此位置,然后ans是用来存入start和end的最大不重复子串的最大值,整个循环结束之后,返回ans就OK了。

class Solution {
    public int lengthOfLongestSubstring(String s) {
       int n =s.length(),ans =0;
       Map<Character,Integer> map =new HashMap<>();
       for(int end =0,start=0;end<n;end++){
        char alpha =s.charAt(end);
        if(map.containsKey(alpha)){
            start=Math.max(map.get(alpha),start);
        }
        ans =Math.max(ans,end-start+1);
        map.put(s.charAt(end),end+1);
       }
       return ans;
    }
}

感觉这个运行和空间效率还是一般般,我们来优化一下,首先是内存这里,我们用来Map,这玩意还是蛮占空间的,而且查询效率较低,这里我们换数组,接下来的思路是滑动窗口,这里我们还是准备两个指针left和right,然后再来一个max用来记录我们目前碰到的不重复子串的最大值,right用于不断向后获取字符c,在中间先判断字符c在has数组中有无出现过,如果存在,left就向后面移动一位缩小窗口,并记入为false存入数组中,如果不存在就记入为true存入数组中,当循环结束的时候,ans便得到了最大的数值,返回即可。

class Solution {
    public int lengthOfLongestSubstring(String S) {
        char[] s = S.toCharArray(); // 转换成 char[] 加快效率(忽略带来的空间消耗)
        int n = s.length, ans = 0, left = 0;
        boolean[] has = new boolean[128]; // 也可以用 HashSet<Character>,这里为了效率用的数组
        for (int right = 0; right < n; right++) {
            char c = s[right];
            // 如果窗口内已经包含 c,那么再加入一个 c 会导致窗口内有重复元素
            // 所以要在加入 c 之前,先移出窗口内的 c
            while (has[c]) { // 窗口内有 c
                has[s[left++]] = false; // 缩小窗口
            }
            has[c] = true; // 加入 c
            ans = Math.max(ans, right - left + 1); // 更新窗口长度最大值
        }
        return ans;
    }
}

看看结果,直接超过了百分之百的人! 

 

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值