文章目录
题目
1 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解答
方法一: 枚举(暴力求解)
时间复杂度:O(N^2)
空间复杂度:O(1)
//java
class Solution{
public int[] towSum(int[] nums, int target){
//创建一个数组 来存放数据
int[] a = new int[2];
int n = nums.length;
for(int i=0;i<n;++i){
for(int j =i+1;j<n;++j){
if(nums[i] +nums[j] == target){
a[0] = i;
a[1] = j;
return new a;
}
}
}
return new int[0];
}
}
class Solution:
def twoSum(self,nums):
n = len(nums)
for i in range(n):
for j in range(i+1,n):
if nums[i] + nums[j] == target:
return [i,j]
return []
方法二: 哈希表
15 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解答
方法一:暴力求解
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Set result = new HashSet();
for(int i =0; i < nums.length; i++) {
for (int j = i +1; j< nums.length; j++) {
for(int l = j +1; l < nums.length; l++) {
if (nums[i] + nums[j]+nums[l] == 0) {
List result2 = new ArrayList();
result2.add(nums[i]);
result2.add(nums[j]);
result2.add(nums[l]);
Collections.sort(result2);
result.add(result2);
}
}
}
}
return new ArrayList<>(result);
}
}
方法二:排序 + 双指针(排序后夹逼)
时间复杂度 O(N^2)
空间复杂度 O(1)
class Solution {
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList();
int len = nums.length;
if(nums == null || len < 3) return ans;
Arrays.sort(nums); // 排序
for (int i = 0; i < len ; i++) {
if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
int L = i+1;
int R = len-1;
while(L < R){
int sum = nums[i] + nums[L] + nums[R];
if(sum == 0){
ans.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) L++;
else if (sum > 0) R--;
}
}
return ans;
}
}
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 去除例外
n = len(nums)
res = []
if (not nums or n < 3):
return []
# 排序
nums.sort()
# 创建一个列表用来保存数据
res = []
# 遍历排序后的数组
for i in range(n):
# 若 nums[i]>0nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 00,直接返回结果。
if (nums[i] > 0):
return res
# 对于重复元素:跳过,避免出现重复解
if (i > 0 and nums[i] == nums[i - 1]):
continue
# 令左指针 L=i+1L=i+1,右指针 R=n-1R=n−1,当 L<RL<R 时,执行循环
L = i + 1
R = n - 1
while (L < R):
# 找到结果,就输入列表中
if (nums[i] + nums[L] + nums[R] == 0):
res.append([nums[i], nums[L], nums[R]])
while (L < R and nums[L] == nums[L + 1]):
L = L + 1
while (L < R and nums[R] == nums[R - 1]):
R = R - 1
L = L + 1
R = R - 1
# 若和大于 0,说明nums[R] 太大,R 左移
elif (nums[i] + nums[L] + nums[R] > 0):
R = R - 1
# 若和小于 0,说明 nums[L] 太小,L 右移
else:
L = L + 1
return res
复习:
java集合
- Java 集合框架主要包括两种类型的容器: 一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。
- Collection 又有 3 种子类型,List、Set 和 Queue
遍历 ArrayList
import java.util.*;
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用 For-Each 遍历 List
for (String str : list) { //也可以改写 for(int i=0;i<list.size();i++) 这种形式
System.out.println(str);
}
//第二种遍历,把链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //这里也可以改写为 for(String str:strArray) 这种形式
{
System.out.println(strArray[i]);
}
//第三种遍历 使用迭代器进行相关遍历
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
}
遍历 Map
import java.util.*;
public class Test{
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
Java Iterator(迭代器)
Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法
迭代器 it 的两个基本操作是 next 、hasNext 和 remove。
调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。
调用 it.hasNext() 用于检测集合中是否还有元素。
调用 it.remove() 将迭代器返回的元素删除。
package com.company;
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// 创建集合
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
// 获取迭代器
Iterator<String> it = sites.iterator();
// 输出集合中的第一个元素
System.out.println(it.next());
// 输出集合中的所有元素
//让迭代器 it 逐个返回集合中所有元素最简单的方法是使用 while 循环:
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
Java ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
以下情况使用 ArrayList :
频繁访问列表中的某一个元素。
只需要在列表末尾进行添加和删除元素操作。
package com.company;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
//实例化对象
ArrayList<String> sites = new ArrayList<String>();
//增
sites.add("Google");
sites.add("Runoob");
sites.add("Runoob");
sites.add("Weibo");
sites.add("Google");
System.out.println(sites);
//访问
System.out.println(sites.get(1));
//修改
sites.set(1, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值
System.out.println(sites);
//删除
sites.remove(1); // 删除第四个元素
System.out.println(sites);
//计算大小
System.out.println(sites.size());
//排序 (按字母大小)
Collections.sort(sites); // 字母排序
for (String i : sites) {
System.out.println(i);
}
}
}
Java LinkedList
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
与 ArrayList 相比,LinkedList 的增加和删除对操作效率更高,而查找和修改的操作效率较低。
以下情况使用 LinkedList :
你需要通过循环迭代来访问列表中的某些元素。
需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
package com.company;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
// 实例化对象
LinkedList<String> sites = new LinkedList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
System.out.println(sites);
//末尾添加元素
sites.addLast("Wiki");
System.out.println(sites);
// 使用 removeFirst() 移除头部元素
sites.removeFirst();
System.out.println(sites);
// 使用 getFirst() 获取头部元素
System.out.println(sites.getFirst());
// 使用 getLast() 获取尾部元素
System.out.println(sites.getLast());
//迭代元素
for (int size = sites.size(), i = 0; i < size; i++) {
System.out.println(sites.get(i));
}
}
}