27. 移除元素
class Solution {
public int removeElement(int[] nums, int val) {
if(nums==null || nums.length==0){
return 0;
}
int i=0;
for(int j=0; j<nums.length; j++){
if(nums[j]!=val){
nums[i++]=nums[j];
}
}
return i;
}
}
344. 反转字符串
class Solution {
public void reverseString(char[] s) {
for(int i=0,j=s.length-1; i<j; i++,j--){
char temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
}
54. 替换数字
import java.util.*;
public class Main{
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
//String不可变,StringBuilder可变
StringBuilder sb = new StringBuilder();
for(int i=0;i<str.length();i++){
char ch = str.charAt(i);
if(ch>='0' && ch<='9'){
sb.append("number");
}else{
sb.append(ch);
}
}
System.out.println(sb);
}
}
151. 翻转字符串里的单词
不额外开辟空间的做法比较繁琐,没做
206. 反转链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null){
return null;
}
ListNode pre=null;
ListNode current=head;
while(current!=null){
ListNode post=current.next;
current.next=pre;
pre=current;
current=post;
}
return pre;
}
}
19.删除链表的倒数第N个节点
快慢指针解法:
- 开始时 fast 指针和 slow 指针都指向 head 节点(第 1 个节点)
- 然后,slow 不动,fast 指针先走
- 等到某一轮循环 fast 走到第 n+2 个节点时,那么在本轮循环 slow 就可以开始走了。本轮循环结束时,fast 走到第 n+2 个节点,slow 走到第 2 个节点,于是 fast 比 slow 快 n 步
- 此后的每一轮循环,fast 和 slow 同时前走一个节点,即 fast 一直比 slow 快 n 步
- 这样,当 fast 为 null(最后一个节点的后面)时,slow 就指向倒数第 n 个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null){
return null;
}
ListNode preHead=new ListNode(0,head);
int i=1;
ListNode preSlow=preHead;
ListNode fast=head, slow=head;
while(fast!=null){
fast=fast.next;
i++;
if(i>n+1){//本轮fast走了n+2,slow还停在1,所以slow要开始出动了
slow=slow.next;
preSlow=preSlow.next;
}
}
preSlow.next=slow.next;
return preHead.next;
}
}
160. 链表相交
快慢指针解法:先统计两个链表的长度,如果两个链表的长度不一样,就让链表长的先走,直到两个链表长度一样,这个时候两个链表再同时每次往后移一步,看节点是否一样,如果有相等的,说明这个相等的节点就是两链表的交点,否则如果走完了还没有找到相等的节点,说明他们没有交点,直接返回 null
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null || headB==null){
return null;
}
int lengthA=listLength(headA);
int lengthB=listLength(headB);
ListNode longP=null;
ListNode shortP=null;
int lengthAB=-1;
if(lengthA>lengthB){
longP=headA;
shortP=headB;
lengthAB=lengthA-lengthB;
}else{
longP=headB;
shortP=headA;
lengthAB=lengthB-lengthA;
}
// 让长度长的链表指针先走lengthAB步
int i=0;
while(i<lengthAB){
longP=longP.next;
i++;
}//此循环结束时,longP指向编号为lengthAB的节点(编号从0开始),即第lengthAB+1个节点
//而shortP还指向head节点也就是第1个节点,所以此时两者离链表尾的距离相同了
while(longP!=null){
if(longP==shortP){
return longP;
}
longP=longP.next;
shortP=shortP.next;
}
return null;
}
private int listLength(ListNode head){
ListNode pointer=head;
int length=0;
while(pointer!=null){
length++;
pointer=pointer.next;
}
return length;
}
}
142. 环形链表II
快慢指针解法,先说结论:
- 快指针每次走 2 步,慢指针每次走 1 步
- 若链表无环,一直等到快指针走到链表尾部,快慢指针也不会相遇
- 若链表有环,快指针一定会在将来与慢指针重合,该位置记为 meet
- 链表开始位置记为 start,则 start 与入环点的距离 == meet 与入环点的距离。
- 此时,meet 和 start 同时前进,二者一定会在入环点相遇,返回该入环点即可
(关于上面结论的证明在这篇文章:https://blog.csdn.net/Claffic/article/details/129431980)
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){//找到相遇点了
//start与meet同时前进,一定会遇到两者重合的点,就是入环的第一个节点
ListNode meet=fast;
ListNode start=head;
while(meet!=start){
meet=meet.next;
start=start.next;
}
return meet;
}
}
// 如果fast走到null了,说明链表无环
return null;
}
}
15. 三数之和
双指针解法:
- 首先将数组排序
- for 循环遍历数组,i 从下标 0 的地方开始,定义 left 在 i+1 的位置,right 在数组结尾的位置
- 在数组中找到 nums[i]、nums[left]、nums[right] 使得三者之和为 0,若找到 left++,right–
- 如果nums[i] + nums[left] + nums[right] > 0,说明三数之和大了,因为数组经过了排序,所以 right–
- 如果 nums[i] + nums[left] + nums[right] < 0 说明三数之和小了,left++,才能让三数之和大一些
- 重复上面三步操作,直到 left 与 right 相遇,i 再指向下一个数组元素。
在本解法中,去重操作统一交给了 Set 集合,执行用时较长,但能过,且省去许多考虑。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
if(nums==null || nums.length<3){
return null;
}
Arrays.sort(nums);
Set<List<Integer>> set = new HashSet<>();
for(int i=0;i<nums.length-2;i++){
int left=i+1;
int right=nums.length-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum==0){
set.add(geneSorted(nums[i], nums[left], nums[right]));
left++;
right--;
}else if(sum<0){
left++;
}else{
right--;
}
}
}
return new ArrayList<>(set);
}
// 传入三个整数,返回三个整数构成的List集合,集合中的元素是升序排列的
private List<Integer> geneSorted(int a, int b, int c){
List<Integer> list=new ArrayList<>();
list.add(a);
list.add(b);
list.add(c);
Collections.sort(list);
return list;
}
}