1.
public void merge(int A[], int m, int B[], int n) {
int i = m-1;//m表示A数组有几个元素
int j = n-1;//n表示B数组有几个元素
int k = m+n-1;
while(i >= 0 && j >= 0) {
if(A[i] > B[j]) {
A[k] = A[i];
k--;
i--;
}else {
A[k] = B[j];
k--;
j--;
}
}
//1,判断走没走完 2.没走完的把剩下元素拷贝到A数组
while(i >= 0) {//当i<0时走完
A[k] = A[i];
k--;
i--;
}
while (j >= 0) {
A[k] = B[j];//当j<0时走完
k--;
j--;
}
}
2.
//方法一:
public static void func1(String str) {
String str1 = "";
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(!str1.contains(ch+"")) {//字符串拼接任何都为字符串
str1 += ch;
}
}
System.out.println(str1);
}
方法二:
public static String func2(String str) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (stringBuilder.indexOf(ch + "") < 0) {
//通过下标来判断,如果存在了,下标就会大于或等于0
stringBuilder.append(ch);
}
}
return stringBuilder.toString();//这里需要将它转为字符串
}
链表
1.移除链表元素
class Solution {
public ListNode removeElements(ListNode head, int val) {
if (head == null) {//首先判断链表是否为空
return null;
}
ListNode prev = head;//一开始prev等于head节点
ListNode cur = head.next;
while (cur != null) {
if (cur.val == val) {//值相同就删除
prev.next = cur.next;
cur = cur.next;
} else {//值不同就移位
prev = cur;
cur = cur.next;
}
}
if (head.val == val) {//如果第一个节点的值等于val
head = head.next;//兜底 可以放在前面,但必须要用循环,因为可能存在两个连续相同的值出现
}
return head;
}
}
2.反转链表
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null) {//空链表
return null;
}
if (head.next == null) {//只有一个节点
return head;
}
ListNode cur = head.next;
head.next = null;//得先把头节点的next域置null,不然会形成循环
while (cur != null) {
ListNode curNext = cur.next;//头插法,就是把后面的节点往头节点前面插
cur.next = head;
head = cur;
cur = curNext;
}
return head;
}
}
3.链表中间节点
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {//fast!=null放前面,不然会有空指针异常,fast.next都不为空,那fast肯定也不为空。前面是奇数的条件后面是偶数的条件
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
4.输入一个链表,输出该链表中倒数第k个结点。
public ListNode FindKthToTail(int k){//寻找倒数第k个节点
if(k <= 0 || head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while(k-1 > 0){//先让fast走k-1步
fast = fast.next;
if(fast == null) {//表明k太大了,超过范围了
return null;
}
k--;
}
while(fast.next != null){//然后fast和slow一起走,每次走一步,直到fast走到最后一个节点
fast = fast.next;
slow = slow.next;
}
return slow;
}
5.题目链接
class Solution {
public ListNode mergeTwoLists(ListNode A, ListNode B) {// A,B代表两个链表的头节点
ListNode newHead = new ListNode();// 创建一个傀儡节点
ListNode tmp = newHead;
while (A != null && B != null) {
if (B.val > A.val) {
tmp.next = A;
tmp = tmp.next;
A = A.next;
} else {
tmp.next = B;
tmp = tmp.next;
B = B.next;
}
}
if (A != null) {// 剩下的合并起来
tmp.next = A;
}
if (B != null) {// 剩下的合并起来
tmp.next = B;
}
return newHead.next;
}
}
6.链表分割
public class Partition {
public ListNode partition(ListNode pHead, int x) {
// write code here
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
ListNode cur = pHead;
while (cur != null) {
if (cur.val < x) {
if (bs == null) { //第一次插入
bs = be = cur;
} else {//不是第一次插入
be.next = cur;
be = be.next;
}
} else {
if (as == null) {
as = ae = cur;
} else {
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
if (bs == null) { //如果b表为空,返回a表
return as;
}
be.next = as;//连接a表
if (as != null) {
ae.next = null;//当最大的值放在最后面时,next域要改掉,不然要形成循环。
}
return bs;
}
}
7.判断回文
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {//头节点
// write code here
ListNode fast = A;
ListNode slow = A;
while (fast != null && fast.next != null) { //1.找中间节点
fast = fast.next.next;
slow = slow.next;
}
//2.将中间节点以后的节点反转
ListNode cur = slow.next;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;
}
//3.反转完成
while(A != slow){//节点不能比较大小,只有值可以。
if(A.val != slow.val) {
return false;
}
if(A.next == slow){//偶数情况下
return true;
}
A = A.next;
slow = slow.next;
}
return true;
}
}
8.相交链表
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//1.分别求2个链表的长度
int lenA = 0;
int lenB = 0;
ListNode pL = headA;//假设pL指向的链表是最长的链表
ListNode pS = headB;//假设pS指向的链表是最短的链表
while(pL != null) {
lenA++;
pL = pL.next;
}
while(pS != null) {
lenB++;
pS = pS.next;
}
pL = headA;
pS = headB;
int len = lenA - lenB;//比较谁的链表长度更长
if(len < 0) {//修正pL和pS
pL = headB;
pS = headA;
len = lenB - lenA;
}
//2.让长的链表先走差值步
for(int i = 0; i < len; i++) {
pL = pL.next;
}
//3.相遇的点
while(pL != pS) {
pL = pL.next;
pS = pS.next;
}
return pL;
}
}
9.环形链表
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null) {
return false;//没环
}
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;
}
}
10.环形链表二
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) {
break;
}
}
if(fast == null || fast.next == null) {
return null;//无环
}
fast = head;
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
11.删除链表中重复的节点
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
ListNode cur = pHead;
ListNode newHead = new ListNode(-1);//实例化但需要带一个参数
ListNode tmpHead = newHead;//傀儡节点
//遍历链表的每个节点
while (cur != null) {
if (cur.next != null && cur.val == cur.next.val) {
//一直让cur走到不重复的节点 然后把这个节点 加入到不重复的链表当中
while (cur.next != null && cur.val == cur.next.val) {
cur = cur.next;
}
cur = cur.next;
}else {
tmpHead.next = cur;
tmpHead = tmpHead.next;
cur = cur.next;
}
}
tmpHead.next = null;//防止重复的节点在末尾,不然删不掉
return newHead.next;
}
}
栈
1.
class Solution {
public boolean isValid(String s) {
//只要是左括号就入栈
//遇到右括号就开始匹配
//1.栈为空
//2.栈不为空,但是字符串遍历完了,有剩余
//3.和栈顶不匹配
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if(ch == '(' || ch == '{' || ch == '[') {
//左括号
stack.push(ch);
}else {
//右括号
if(stack.empty()) {//右括号不匹配
return false;
}
char top = stack.peek();//此时栈顶的元素
if(ch == ')' && top == '(' || ch == '}' && top == '{' || ch == ']' && top == '[') {
stack.pop();//如果符合则弹出
}else {
return false;
}
}
}
if(!stack.empty()) {
return false;//栈内还有剩余,左括号不匹配
}
return true;
}
}
2.
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(String s:tokens) {
if(!isOperation(s)) {
//数字
stack.push(Integer.parseInt(s));
}else {
//加减乘除中的一个
int num2 = stack.pop();//注意顺序 操作符左右两侧
int num1 = stack.pop();
switch (s){
case "+":
stack.push(num1+num2);
break;
case "-":
stack.push(num1-num2);
break;
case "*":
stack.push(num1*num2);
break;
case "/":
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}
private boolean isOperation(String s) {
if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
return true;
}
return false;
}
}
2024.5.17
1.栈
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> MinStack;
public MinStack() {
this.stack = new Stack();
this.MinStack = new Stack();
}
public void push(int val) {
this.stack.push(val);
if(this.MinStack.empty()) {//一开始两个栈都是空的
this.MinStack.push(val);
}else {
if(val <= this.MinStack.peek()) {
this.MinStack.push(val);
}
}
}
public void pop() {
if(!this.stack.empty()){//不为空就弹出
int ret = this.stack.pop();
if(this.MinStack.peek() == ret) {//如果正常栈弹出的元素和最小栈的栈顶元素相等
this.MinStack.pop();
}
}
}
public int top() {
if(this.stack.empty()){//返回正常栈的栈顶元素
return -1;
}
return this.stack.peek();
}
public int getMin() {//返回最小栈的栈顶元素
if(this.MinStack.empty()){
return -1;
}
return this.MinStack.peek();
}
}
2.就是可以判断出他的不可能序列
//i遍历PushV数组,每次拿到一个数据就放到 栈当中去
//j遍历popV数组
public Boolean IsPopOrder (int[] pushV, int[] popV) {
Stack<Integer> stack = new Stack<>();
int j = 0;
for(int i = 0; i < pushV.length; i++) {
stack.push(pushV[i]);
while(!stack.empty() && j < popV.length && stack.peek() == popV[j]) {
stack.pop();
j++;
}
}
return stack.empty();
}