一直不太懂什么是算法时间复杂度? - 简书,要好好理解一下
https://baijiahao.baidu.com/s?id=1700279574407263893&wfr=spider&for=pc
简单
Q1、两数之和https://leetcode-cn.com/problems/two-sum/
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
// // 双重for循环
// for(int i =0,n = nums.length;i<n;i++){
// for(int j = i+1;j<n;j++){
// if((nums[i] + nums[j])-target == 0){
// res[0]=i;
// res[1]=j;
// return res;
// }
// }
// }
// 一次循环,使用HashMap,建立k-v关系 K为数值 v为索引
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i = 0,n=nums.length;i<n;i++){
// 每次在放入map之前先判断
if(map.containsKey(nums[i])){
res[0]=i;
res[1]=map.get(nums[i]);
return res;
}
map.put(target-nums[i],i);// 数值做k,索引做值
}
return res;
}
}
Q2、判断链表是否有环 https://leetcode-cn.com/problems/linked-list-cycle/
方法一:哈希散列表
public class Solution {
public boolean hasCycle(ListNode head) {
// 哈希散列表或快慢指针
// 链表->内存不连续,新增/删除方便,查找不方便。对比集合,内存连续,查找方便,插入不方便
// HashSet特点:不允许有重复元素,
Set set = new HashSet();
if(head ==null || head.next==null) {return false;}
ListNode slow = head;
while(slow!=null){
if(set.contains(slow)){
return true;
}
set.add(slow);
slow=slow.next;
}
return false;
}
}
方法二:快慢指针
public class Solution {
public boolean hasCycle(ListNode head) {
// 快慢指针
ListNode fast = head;
ListNode slow = head;
// 空链表、单节点链表一定没有环
while(fast != null && fast.next != null){
fast = fast.next.next;// 快指针:一次移动两步
slow = slow.next; // 慢指针:一次移动一步
if(fast == slow){ // 快慢指针相遇,证明有环
return true;
}
}
return false;// 正常走到链表末尾,证明没有环
}
}
Q3、三数之和http:// https://leetcode-cn.com/problems/3sum/
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
// 看过题解后 排序+双指针
Arrays.sort(nums);
// 双指针 头尾
int n = nums.length;
for(int i = 0;i<n;i++){
int first = nums[i]; // 先定位一个数字,后就是特殊的两数之和
if(i > 0 && nums[i-1] == nums[i]){
continue; // 为保证无重复,当与前一个元素相等时,跳出本次循环
}
int target = -first; // 特殊的和
int third = n - 1; // 定义第三个数为最大值,指针为最末尾
// 循环定位b
for(int j = i + 1;j < n;j++){
if(j > i + 1 && nums[j] == nums[j-1]){
continue;
}
while(j < third && nums[j] + nums[third] > target){
--third;
}
if(j == third){
break; // 如果指针重合,代表本次无需再遍历,直接结束循环体即可
}
if((nums[j] + nums[third] == target)){
List<Integer> li = new ArrayList<>();
li.add(nums[i]);
li.add(nums[j]);
li.add(nums[third]);
lists.add(li);
}
}
}
return lists;
}
}
Q4、环形链表2https://leetcode-cn.com/problems/linked-list-cycle-ii/
方法一:哈希散列表 O(n) O(n)空间
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode node = head;
// 定义一个Set集合 因为Set集合中的元素不允许重复
Set<ListNode> set = new HashSet<ListNode>();
while(node != null){
if(set.contains(node)){
return node; // 返回当前节点
}else{
set.add(node);
}
node = node.next; // 向后移动一个节点
}
return null;
}
}
方法二:快慢指针 O(n) O(1)空间
假设存在环,则快慢指针一定会相遇。相遇时快指针fast走的长度是a+n(b+c)+b=a+(n+1)b+nc;
而快指针走的长度是慢指针的2倍,所以a+(n+1)b+nc = 2(a+b); => a = (n-1)b+nc = c+(n-1)(b+c)
这里的(n-1)(b+c)理解为走了(n-1)圈环,可以看出下图中的a与c长度相等。当快慢指针相遇时,再定义一个指针pointer指向链表头部head,此后pointer与slow每次都移动一个位置,最终会在入环点处相遇。这是将pointer返回即可
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null){
return null;
}
// 快慢指针
ListNode slow = head,fast = head;
while(fast != null){
slow = slow.next;// 慢指针移动一步
if(fast.next != null){
fast = fast.next.next;// 快指针移动两步
}else{
return null;
}
// 快慢指针相遇
if(fast == slow){
ListNode ptr = head;// 再定义一个指针指向头节点
// 当头节点与慢指针相遇时就是入环点
while(ptr != slow){
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
}
Q5、创建一个对象的详细过程(JVM相关)