2024-11-06-Wed-T-数据结构与算法

1. 简单

1.1 两数之和

给定一个整数数组 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]
 

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
 

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
// O(n^2)
//按照距离寻找
//相邻, 间隔一位, 间隔二位, 间隔三位....
//01, 12,23,34,45,56....
//02, 13, 24, 35....
class Solution {
    public int[] twoSum(int[] nums, int target) {
        for(int i = 1; i < nums.length; i++){
            for(int j = i; j < nums.length; j++){
                if(nums[j-i] + nums[j] == target){
                    return new int[]{j-i, j};
                }
            }
        }
        return new int[]{0,0};
    }
}


//哈希表
//注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
// 使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
// 这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
// 时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。
// 空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。

class Solution {
    public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i]; // 寻找 target - x
        if (map.containsKey(complement)) { // 如果存在,返回索引
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i); // 将 x 插入哈希表
    }
    throw new IllegalArgumentException("No two sum solution");
}
}

1.2 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head = null, tail = null;
        int carry = 0;
        while (l1 != null || l2 != null) {
            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;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        if (carry > 0) {
            tail.next = new ListNode(carry);
        }
        return head;
    }
}

1.3 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长"子串"的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成


//滑动窗口
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        if(n<=1){
            return n;
        }
        int l = 0, r = 1;
        HashSet<Character> set = new HashSet<>();
        set.add(s.charAt(l));
        int res = 0;
        while(r<n){
            while(r<n && !set.contains(s.charAt(r))){
                set.add(s.charAt(r));
                r++;
            }
            res = Math.max(res, r-l);
            set.remove(s.charAt(l)); // 
            l++;
        }
        return res;
    }
}


1.4 寻找两个正序数组的中位数

2. 一般

3. 困难

posted @ 2025-11-23 21:18  飞↑  阅读(3)  评论(0)    收藏  举报