力扣(LeetCode)Java刷题 简单+中等(第三期)

本文深入解析了多个经典算法问题,包括三数之和、最接近的三数之和、四数之和、电话号码的字母组合、删除链表的倒数第N个节点以及有效的括号,提供了详细的代码实现与算法思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 三数之和(中等题)
    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
    注意:答案中不可以包含重复的三元组。
    示例:
    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    满足要求的三元组集合为:
    [
    [-1, 0, 1],
    [-1, -1, 2]
    ]
    方法代码:
class Solution {
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        int len = nums.length;
		if(nums.length < 3) return result;
		Arrays.sort(nums);
		for(int i = 0 ; i < len; i++) {
			if(nums[i] > 0 ) break;
			if(i>0 && nums[i] == nums[i-1])
				continue;
			int l = i+1, r = len -1;
			while(l < r) {
				int sum = nums[i] + nums[l] + nums[r];
				if(sum == 0) {
					result.add(Arrays.asList(nums[i],nums[l],nums[r]));
					while(l < r && nums[l] == nums[l+1]) l++;
					while(l < r && nums[r] == nums[r-1]) r--;
					l++;
					r--;
				}
				else if(sum > 0) r--;
				else if(sum < 0) l++;
			}
		}
		return result;
    }
}

方法解析:
标签:数组遍历
首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向nums[i]后面的两端,数字分别为nums[l] 和nums[r],计算三个数的和 sum判断是否满足为0,满足则添加进结果集
如果 nums[i]大于0,则三数之和必然无法等于0,结束循环
如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
当 sum== 0 时,nums[l] == nums[l+1] 则会导致结果重复,应该跳过,L++
当 sum == 0时,]nums[r] ==nums[r−1] 则会导致结果重复,应该跳过,R–
时间复杂度:O(n^2),n为数组长度

  1. 最接近的三数之和(中等题)
    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
    例如,给定数组 nums = [-1,2,1,-4], 和 target = 1。
    与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2)。
    方法代码:
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
		 		int len = nums.length;
                int result = nums[0] + nums[1] +nums[2];
		 		if(len < 3) return target;
                if(len == 3) return result;
		 		
		 		int sum = Math.abs(target - result);
		 		for(int i = 0 ;i < len - 2 ; i++) {
		 			int l = i + 1;
		 			int r = len -1;
		 			while(l < r) {
		 				int ans = nums[i] + nums[l] + nums[r];
		 				if(sum > Math.abs(target - ans)) {
		 					sum = Math.abs(target - ans);
		 					result = ans;
		 				}
		 				if(sum == 0) return target;
		 				if(ans > target) {
		 					while(l < r && nums[r] == nums[r-1]) r--;
		 					r--;
		 					
		 				}
		 				else if(ans < target){
		 					while(l < r && nums[l] == nums[l+1]) l++;
		 					l++;
		 					
		 				}
		 				
		 			}
		 			
		 			
		 		}
		 		return result;

    }
}

方法解析:
标签:排序和双指针
本题目因为要计算三个数,如果靠暴力枚举的话时间复杂度会到 O(n^3),需要降低时间复杂度
首先进行数组排序,时间复杂度 O(nlogn)
在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i]
再使用前指针指向 l = i + 1 处,后指针指向 r = nums.length - 1 处,也就是结尾处
根据 ans = nums[i] + nums[l] + nums[r] 的结果,判断 ans 与目标 target 的距离,如果更近则更新结果result
同时判断 ans 与 target 的大小关系,因为数组有序,如果 ans > target 则 r–,如果 sum < target 则 l++,如果 ans == target 则说明距离为 0 直接返回结果,整个遍历过程,固定值为 n 次,双指针为 n 次,时间复杂度为 O(n^2)
总时间复杂度:O(nlogn) + O(n^2) = O(n^2)

  1. 四数之和(中等题)
    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
    注意:
    答案中不可以包含重复的四元组。
    示例:
    给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
    满足要求的四元组集合为:
    [
    [-1, 0, 0, 1],
    [-2, -1, 1, 2],
    [-2, 0, 0, 2]
    ]
    方法代码:
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
       List<List<Integer>> res = new ArrayList<>();
		int len = nums.length;
		if(len < 4 || nums == null) return res;
		Arrays.sort(nums);
		for(int i = 0 ; i < len-3 ; i++) {
            if((nums[i] + nums[len-1] + nums[len-2] + nums[len-3]) < target)
                continue;
            if((nums[i] + nums[i+1] + nums[i+2] + nums[i+3]) > target)
                continue;
			for(int j = len - 1 ; j >= 3; j--) {
					if(i < j) {
						int r = j-1;
						int l = i+1;
						while(l < r) {
							int sum = nums[i] + nums[j] + nums[r] + nums[l];
							if(sum == target) {
								ArrayList<Integer> s = new ArrayList<>();
								s.add(nums[i]);
								s.add(nums[l]);
								s.add(nums[r]);
								s.add(nums[j]);
								res.add(s);
								while(l < r && nums[l] == nums[l + 1]) l++;
								while(l < r && nums[r] == nums[r - 1]) r--;
								l++;
								r--;
							}
							else if(sum > target) {
								while(l < r && nums[r] == nums[r - 1]) r--;
								r--;
							}
							else if (sum < target) {
								while(l < r && nums[l] == nums[l + 1]) l++;
								l++;
							}
						}
					}
					
				while(i < j && nums[j] == nums[j-1]) j--;
			}
			while(i < len-3 && nums[i] == nums[i+1]) i++;
		}
		return res;
    }
}

方法解析:
该题和上题三数之和有点相似,只不过这道题算是用了三个指针吧,先把第一个和最后一个给固定住,然后其余两个根据sum的值来进行调节,之后在移动最后一个指针,再重复上一步,最后与第一个相遇之后,第一个指针再往后移。

  1. 电话号码的字母组合(中等题)
    给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
    给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
    在这里插入图片描述
    示例:
    输入:“23”
    输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
    方法代码:
class Solution {
    String[] strs = {" ", "*" , "abc" , "def" , "ghi" , "jkl" , "mno" , "pqrs" , "tuv"
			, "wxyz"} ;
	List<String> res = new ArrayList<>();
	public List<String> letterCombinations(String digits) {
		if(digits == null || digits.length() == 0) return new ArrayList<>();
		combination(digits, "", 0);
		return res;

    }
	void combination(String digits ,String letter, int index ) {
		if(index == digits.length()) {
			res.add(letter);
			return;
		}
		String s = strs[digits.charAt(index)-'0'];
		for (int i = 0; i < s.length(); i++) {
			combination(digits , letter + s.charAt(i) , index+1);
			
		}
		
	}
}

方法解析:
该方法是用递归的方法来进行解决的,每次对letter与新数字所对应的字母依次进行拼接,知道全部数字都遍历过一遍,把最终的得到的letter添加到list集合中。

  1. 删除链表的倒数第N个节点(中等题)
    给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
    示例:
    给定一个链表: 1->2->3->4->5, 和 n = 2.
    当删除了倒数第二个节点后,链表变为 1->2->3->5.
    说明:
    给定的 n 保证是有效的。
    方法代码:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode first = head;
            ListNode second = head;
            for(int i = 0 ; i < n; i++){
                if(first == null){
                    return null;
                }
                else{
                    first = first.next;
                }
            }
            if(first == null) return head.next;
            while(first.next !=null){
                first = first.next;
                second = second.next;
            }
            second.next = second.next.next;
            return head;
    }
}

方法解析:
该方法是通过指针的方法,先让第一个指针走n步,然后让第一个和第二个指针同时走,当第一个指针下一个结点为NULL时,那么第二个指针的下一个结点就是倒数第n个结点,进行删除。该题还可用栈来进行解决。

  1. 有效的括号(中等题)
    给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
    有效字符串需满足:
    左括号必须用相同类型的右括号闭合。
    左括号必须以正确的顺序闭合。
    注意空字符串可被认为是有效字符串。
    示例 1:
    输入: “()”
    输出: true
    示例 2:
    输入: “([)]”
    输出: false
    方法代码:
class Solution {
   public boolean isValid(String s) {
        int len = s.length();
        char[] c = s.toCharArray();
        char[] stack = new char[len];
        int top = -1;
        for(int i = 0; i < len ;i++){
            if(c[i] == ' ')
                continue;
            if(c[i] == '(' || c[i] == '{' || c[i] == '[') {
            	stack[++top] = c[i];
            	continue;
            }     
            if(c[i] == ')' && (top == -1 || stack[top--] != '('))
                return false;
            if(c[i] == '}' && (top == -1 || stack[top--] != '{'))
                return false;
            if(c[i] == ']' && (top == -1 || stack[top--] != '['))
                return false;
        }
        if(top != -1)
            return false;
        else
            return true;
	}
}

方法解析:该方法是利用栈的思想进行解决的,当遇到左括号时,全部压入栈内,遇到右括号时,栈顶为空返回false,不为空栈顶元素出栈,检查出栈元素是否与右括号相匹配,不匹配则返回false,匹配就继续循环,最后退出循环,如果top为-1,则返回true,否则返回false。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值