因为leetcode的题号会变动,所以先记录一下每一题对应的内容。

  10 Regular Expression Matching 21.6% Hard
  9 Palindrome Number 30.9% Easy
  8 String to Integer (atoi) 13.3% Easy
  7 Reverse Integer 23.6% Easy
  6 ZigZag Conversion 23.3% Easy
  5 Longest Palindromic Substring 22.5% Medium
  4 Median of Two Sorted Arrays 18.2% Hard
  3 Longest Substring Without Repeating Characters 21.6% Medium
  2 Add Two Numbers 22.3% Medium
  1 Two Sum 21.4% Medium

第一题,寻找给定数组中,相加等于目标数的两个数字的下标。

这道题其实很简单,它限定死了每个测试用例都只有一对符合的,那样只要找到合适的就可以跳出循环结束,同时也方便了第二种算法hashmap时一个key对应一个value。用最暴力的方法两重循环,i从0到length,j从i+1到length算,这样时间复杂度是O(n2)。那么为了减少时间复杂度,牺牲空间复杂度,使用hashmap这个数据结构即可,从头遍历数组,首先使用target number减去当前位置的数字,得到另一个加数的值,在hashmap中查找这一值即可,如果hashmap中不含有当前位置的数字,将当前位置的数字加入hashmap,代码如下:

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap map =new HashMap();
        for(int i=0;i<nums.length;i++){
            int num=nums[i];
            int target_num=target-num;
            Object index=map.get(target_num);
            if(index!=null){
                int[] result={(int)index,i};
                    return result;
            }
            map.put(num,i);
        }
        return null;
    }
}

第二题,将两个像链表一样的结构相加。这道题的逻辑很简单,注意特殊情况的处理即可,比如相加后的进位问题,两个链表长度不一样的问题等。

public class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int flag=0;
        ListNode result=null;
        ListNode tail=null;
        while(true){
            if(l1==null&l2==null&flag==0)
                break;
            int val1=(l1==null)?0:l1.val;
            int val2=(l2==null)?0:l2.val; 
            int val=val1+val2+flag;
            flag=val/10;
            val=val%10;
            ListNode node=new ListNode(val);
            if(result==null){
                result=node;
                tail=node;
            }
            else{
                tail.next=node;
                tail=node;
            }
            l1=(l1==null)?null:l1.next;
            l2=(l2==null)?null:l2.next;
        }
        return result;
    }
}

第三题,查找最长的无重复的子串长度。

当然可以两重循环暴力求解,这里选择时间复杂度较低的方法。无重复的子串必定在两个相同字母之间,从头开始遍历字符串,如果遇到前面出现过的字母,则计算当前子串的长度是否超过了记录的最大值,如果超过了则替换,否则从上一次出现的字母+1的位置开始重新查找最长子串。这里需要一个数组来记录某个字母是否出现过了。

这道题中不只是26个字母,因为这里设定的数组长度为256。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        boolean[] exist=new boolean[256];
        int i=0,j=0;
        int maxLen=0;
        for(int n=0;n<s.length();n++){
            if(exist[s.charAt(n)]){
                maxLen=Math.max(maxLen,j-i);
                for(;i<n;i++){
                    if(s.charAt(n)==s.charAt(i)){
                        i++;
                        break;
                    }
                    else{
                         exist[s.charAt(i)]=false;
                    }
                }  
            }
            else{
                exist[s.charAt(n)]=true;
            }
            j++;
        }
        maxLen=Math.max(maxLen,j-i);
        return maxLen;
    }
}

第四题,查找两个已经排好序的数组中的中位数,时间复杂度为O(log(m+n))。

类似算法在英文的算法教程中出现过,本题中我们是要查找这两个数组中第(m+n)/2和第(m+n)/2+1大的数字,实质上为查找第K大的数字。需要注意的一点,数组长度可能小于k/2,此时该数组直接取最大值比较,而另一个数组的比较位置也不是k/2,即分裂点并不一定都是k/2,要考虑全面情况。具体的方法可以见其他专门讲这一部分的blog吧。主要java不像C/C++用指针操作数组方便,因为比起C/C++的实现多了两个参数用来记录当前数组的起始下标。

public class Solution {
    public double findK(int[] nums1, int[] nums2, int k, int n1, int n2,int n1_l,int n2_l){
        //System.out.println(n1+" "+n2+" "+k);
        if(n1_l>n2_l){
            return findK(nums2,nums1,k,n2,n1,n2_l,n1_l);
        }
        if(n1_l==0){
            return nums2[n2+k-1];
        }
        if(k==1){
            return Math.min(nums1[n1], nums2[n2]);
        }
        int point1=Math.min(k/2,n1_l);
        int point2=k-point1;
        if(nums1[n1+point1-1]<nums2[n2+point2-1]){
            return findK(nums1,nums2,k-point1,n1+point1,n2,n1_l-point1,n2_l);
        }
        else if(nums1[n1+point1-1]>nums2[n2+point2-1]){
            return findK(nums1,nums2,k-point2,n1,n2+point2,n1_l,n2_l-point2);
        }
        else{
            return nums1[n1+point1-1];
        }
    }
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int k=nums1.length+nums2.length;
        if(k%2==1){
             return findK(nums1,nums2,k/2+1,0,0,nums1.length,nums2.length);
        }
        else
             return (findK(nums1,nums2,k/2,0,0,nums1.length,nums2.length)+findK(nums1,nums2,k/2+1,0,0,nums1.length,nums2.length))/2;
    }
}
View Code

相关文章:

  • 2022-12-23
  • 2021-11-09
  • 2021-05-15
  • 2021-10-07
  • 2021-07-09
  • 2021-08-30
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-04-07
  • 2021-12-05
  • 2021-05-19
  • 2022-12-23
  • 2021-05-30
相关资源
相似解决方案