杨辉三角
OJ链接:杨辉三角
思路:每一行的第一列和最后一列都是1,其余列是都是上一行的j和j-1的和,我们实例化一个二维顺序表,遍历这个杨辉三角,往顺序表内存入即可。
代码:
public static List> generate(int numRows) {
List> ret= new ArrayList<>();
for(int i=0;i list=new ArrayList<>();
for(int j=0;j<=i;j++){
if(j==0 || j==i){list.add(1);}
else if(i>1){
list.add(ret.get(i-1).get(j-1)+ret.get(i-1).get(j));
}
}
ret.add(list);
}
return ret;
}
原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)
OJ链接:数组移除元素
思路:题目说明了元素的顺序可以改变。不需要考虑数组中超出新长度后面的元素。,
所以每出现一个和val相同的元素,我们就拿他和数组最后的元素替换,要注意的是,每替换一次,数组的长度要减小。
代码:
public int removeElement(int[] nums, int val) {
int flag = 0;
for(int i=0;i
删除排序数组中的重复项
OJ链接:数组移除元素
思路:由于数组已经升序,所以重复项会出现在一起,我们找到重复项后面的数组整体前移,从而将重复项覆盖,每次移动要记录下覆盖的重复项个数,然后返回新的数组长度。
代码:
class Solution {
public int removeDuplicates(int[] nums) {
int flag = 0;
for(int i = 0; i < nums.length - flag; i++) {
int j = i + 1;
while (j < nums.length - flag && nums[j] == nums[i]) {
j++;
}
flag += j - i - 1;
if (j > i + 1) {
for (int k = 0; j + k < nums.length; k++) {
nums[i + 1 + k] = nums[j + k];
}
}
}
return nums.length-flag;
}
}
合并两个有序数组
OJ链接:合并两个有序数组
思路:数组已经有序,所以我们遍历第二个数组,遍历时把比数组1第一个元素小的元素全部放到左边,数组1整体右移,之后从数组2中取得元素,在数组1中找到合适位置放入即可,放入时,数组1插入位置后的元素整体右移。
代码:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int j=0;
int flag=0;
for(int i=0;i=nums2[i]){
for(int k = 0;m+flag-1-k>=j; k++){
nums1[m+flag-k] = nums1[m+flag-1-k];
}
nums1[j]=nums2[i];
flag++;
}else{
while(jnums1[j]){
j++;
}
for(int k = 0;m+flag-1-k>=j; k++){
nums1[m+flag-k] = nums1[m+flag-1-k];
}
nums1[j]=nums2[i];
flag++;
}
}
}
}
删除链表中所有值为value的元素
OJ链接: 删除链表中所有值为value的元素
思路:遍历链表,遍历时记录当前节点与当前节点的前驱节点,删除节点-将前驱节点指向后继节点即可,如果是头结点,直接将新的头结点指向后继节点即可。
代码:
public ListNode removeElements(ListNode head, int val) {
ListNode cur=head;
ListNode prev=null;
while(cur!=null){
if(cur.val==val) {
if(prev==null){
head=head.next;
prev=null;
}else{
prev.next=cur.next;
}
cur=cur.next;
continue;
}
prev=cur;
cur=cur.next;
}
return head;
}
单链表的逆置
OJ链接:单链表的逆置
思路:链表逆置,从头遍历,设定一个前驱节点,开始时将前驱节点置为null,而后遍历时记录当前节点cur,后继节点curnext,前驱节点prev,逆置时,要先记录curnext,然后将当前节点的后继指向前驱prev,在把prev指向当前节点,然后把cur指向后继节点curnext.....最后返回尾部节点即可。
代码:
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null) return null;
ListNode cur=head;
ListNode prev=null;
ListNode next=head;
while(cur!=null)
{
next=cur.next;
cur.next=prev;
prev=cur;
cur=next;
}
return prev;
}
获取链表的中间节点
OJ链接:获取链表的中间节点
思路:定义两个快慢指针,慢指针一次走一步,快指针走两步。当快指针走到尾部时,慢指针指向的即为中间节点,需要注意循环的终止判断语句。
代码:
public ListNode middleNode(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null && fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
获取链表倒数第K个节点
OJ链接:获取链表倒数第K个节点
思路:与快慢指针类似。设定两个指针,让快指针先走k步,使得快慢指针相差K步,从而使得当快指针走到尾部时,慢指针指向倒数第k个节点,这里要注意判断K的合法性。
代码:
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null || k<=0) return null;
ListNode fast=head;
ListNode slow=head;
int flag=1;
while(fast.next!=null){
fast=fast.next;
if(flag>=k) slow=slow.next;
flag++;
}
if(flag
判断链表带环
OJ链接:判断链表带环
思路:如果链表带环,则设定两个快慢指针,当快指针的步长为2,慢指针步长为1,如果带环,一定可以相遇,如果出现尾结点,那么一定不带环。
代码:
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;
}
求环的入口点
OJ链接:求环的入口点
思路:
我们设置快慢两个指针,fast, slow ,fast一次前进两步,slow一次前进一步,设a为第一个节点到入环节点的距离。 a=[0->x],设b为入环口到相遇点的距离。b=[x->L],设c为相遇点到入环口的距离。c=[L->x]当fast,和slow相遇的时候,fast经过的节点是slow的两倍,设slow经过的节点数为S
根据上面的设置 可知 S=a+b ,2S=a+b+c+b,可知 a=c,此时让slow回到第一个节点,fast处于第一次相遇的节点,此时slow从第一个节点出发,各走一步,因为a=c,所以fast,和slow会在入环口第二次相遇,得到要求的节点。
代码:
public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null && fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
fast=head;
while(true){
if(fast==slow) return fast;
fast=fast.next;
slow=slow.next;
}
}
}
return null;
}
判定链表相交
OJ链接:判定链表相交
同时遍历两个链表,求出两个链表长度,让更长的链表先走长度的差值步,然后在同时走,同时走的时候判断两个节点是否相同,如果相同返回true;
代码:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int sizea=0;
int sizeb=0;
ListNode cur1=headA;
ListNode cur2=headB;
while(cur1!=null || cur2!=null){
if(cur1!=null){
sizea++;
cur1=cur1.next;
}
if(cur2!=null){
sizeb++;
cur2=cur2.next;
}
}
cur1=headA;
cur2=headB;
while(sizea>sizeb){
cur1=cur1.next;
sizea--;
}
while(sizeb>sizea){
cur2=cur2.next;
sizeb--;
}
while(cur1!=null && cur2!=null){
if(cur1==cur2) return cur1;
cur1=cur1.next;
cur2=cur2.next;
}
return null;
}public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int sizea=0;
int sizeb=0;
ListNode cur1=headA;
ListNode cur2=headB;
while(cur1!=null || cur2!=null){
if(cur1!=null){
sizea++;
cur1=cur1.next;
}
if(cur2!=null){
sizeb++;
cur2=cur2.next;
}
}
cur1=headA;
cur2=headB;
while(sizea>sizeb){
cur1=cur1.next;
sizea--;
}
while(sizeb>sizea){
cur2=cur2.next;
sizeb--;
}
while(cur1!=null && cur2!=null){
if(cur1==cur2) return cur1;
cur1=cur1.next;
cur2=cur2.next;
}
return null;
}
判定链表是否是回文
OJ链接:判定链表是否是回文
思路:设定快慢指针,将前半个链表逆置(如何逆置见上),然后从中间向两边遍历,判断两个节点的val值是否相同,如果不同返回false;如果两个链表都走完了也没有出现不同,返回true;
代码:
public boolean chkPalindrome(ListNode A) {
ListNode fast=A;
ListNode slow=A;
ListNode prev=null;
while(fast!=null && fast.next!=null){
fast=fast.next.next;
ListNode slownext=slow.next;
slow.next=prev;
prev=slow;
slow=slownext;
}
while(prev!=null && slow!=null){
if(prev.val!=slow.val) return false;
prev=prev.next;
slow=slow.next;
}
if(prev==null && slow==null) return true;
return false;
}
给定 x, 把一个链表整理成前半部分小于 x, 后半部分大于等于 x 的形式
OJ链接:给定 x, 把一个链表整理成前半部分小于 x, 后半部分大于等于 x 的形式
思路:找到第一个小于x的节点,然后把之后小于x的节点接到第一个之后,最后把这一串接到头结点上。
代码;
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Partition {
public ListNode partition(ListNode pHead, int x) {
ListNode cur=pHead;
ListNode prev=null;
ListNode frist=null;
while(cur!=null){
if(cur.val
合并两个有序链表
OJ链接:合并两个有序链表
思路:先把第二个链表中,比第一个链表头结点小的全部移到第一个链表头结点之前,然后更新头结点,之后遍历第二个链表剩下的节点,在第一个链表中找到合适位置插入。
代码:
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode cur1=list1;
ListNode cur2=list2;
ListNode prev=null;
if(list1==null) return list2;
while(cur2!=null && cur2.val<=cur1.val){
ListNode cur2next=cur2.next;
cur2.next=cur1;
list1=cur2;
cur1=list1;
cur2=cur2next;
}
while(cur2!=null){
while(cur1!=null && cur2.val>cur1.val){
prev=cur1;
cur1=cur1.next;
}
ListNode cur2next=cur2.next;
prev.next=cur2;
cur2.next=cur1;
prev=cur2;
cur2=cur2next;
}
return list1;
}