class Solution {
class ListNode{
int value;
ListNode next;
public ListNode(int value, ListNode next) {
this.value = value;
this.next = next;
}
public ListNode(int value) {
this.value = value;
}
public ListNode() {
}
}
public ListNode reverseKGroup(ListNode head, int k) {
//使用栈来保存节点
Stack<ListNode>stack=new Stack<>();
//设置虚拟节点
ListNode virtualNode=new ListNode(0);
ListNode dummy=virtualNode;
ListNode temp=head;
while (true){
int count=0;
//往栈中压入k个节点
while (temp!=null&&count<k){
stack.push(temp);
temp=temp.next;
count++;
}
//如果count!=k,那就把虚拟节点的next指向指向头结点
if(count!=k){
dummy.next=head;
break;//这里必须要退出
}
//如果count==k,那就建链表
while (!stack.isEmpty()){
dummy.next=stack.pop();
dummy=dummy.next;
}
//将新节点的next指向指向temp节点
dummy.next=temp;
//前面k组已经反转完,所以需要把头节点设置为temp
head=temp;
}
return virtualNode.next;
}
}
public ListNode reverseBetween(ListNode head, int left, int right) {
if(left==right){
return head;
}
ListNode virtualNode = new ListNode(0);
virtualNode.next=head;
//1.先找到反转链表的起始节点的前置节点和末尾节点
//前置节点
ListNode pre=virtualNode;
//末尾节点
ListNode end=virtualNode;
for(int i=0;i<left-1;i++){
pre=pre.next;
end=end.next;
}
for(int i=0;i<right-left+1;i++){
end=end.next;
}
//当前反转的起始节点
ListNode cur=pre.next;
//当前反转末尾节点的下一个节点
ListNode curr=end.next;
//2.切断链表
pre.next=null;
end.next=null;
//3.反转这中间的链表
ListNode node = reverse(cur);
//4.搭接链表
pre.next=node;
cur.next=curr;
return virtualNode.next;
}
private ListNode reverse(ListNode head){
ListNode pre=null;
ListNode cur=head;
//3.反转这中间的链表
while (cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
public ListNode deleteDuplicates(ListNode head) {
ListNode virtualNode = new ListNode(0);
ListNode temp = virtualNode;
while (head != null) {
//如果head已到末尾节点,或者当前节点有效
if (head.next == null || head.val != head.next.val) {
temp.next = head;
temp = temp.next;
}
//如果当前节点与下一节点重复
while (head.next != null && head.val == head.next.val) {
//就一直跳过重复节点
head = head.next;
}
head = head.next;
}
temp.next = null;
return virtualNode.next;
}
public int firstMissingPositive(int[] nums) {
int n=nums.length;
for(int i=0;i<n;i++){
//nums[i]应该存放在i-1的位置上
while (nums[i]>=1&&nums[i]<=n&&nums[i]!=nums[nums[i]-1]){
swap(nums,i,nums[i]-1);
}
}
for(int i=0;i<n;i++){
if(nums[i]!=i+1){
return i+1;
}
}
return n+1;
}
private void swap(int []nums,int left,int right){
int temp=nums[right];
nums[right]=nums[left];
nums[left]=temp;
return;
}
List<String> res = new ArrayList<>();
Deque<String> path = new ArrayDeque<>(4);
public List<String> restoreIpAddresses(String s) {
if (s == null || s.length() <= 3 || s.length() > 12) {
return res;
}
int len = s.length();
backTrack(s, len, 0, 4);
return res;
}
//restSeg变量用来表示还有多少段没有被分割
private void backTrack(String str, int len, int begin, int restSeg) {
//如果已经遍历到末尾了
if (begin == len) {
//并且所有段都已被分割
if (restSeg == 0) {
res.add(String.join(".", path));
}
//只要遍历到末尾就返回
return;
}
//每段最多为取3位
for (int i = begin; i < begin + 3; i++) {
if (i >= len) {
break;
}
//如果剩下的数字无法被完全3位数分割
if (restSeg * 3 < len - i) {
continue;
}
if (check(str, begin, i)) {
String segment = str.substring(begin, i + 1);
path.addLast(segment);
backTrack(str, len, i + 1, restSeg - 1);
path.removeLast();
}
}
}
private boolean check(String str, int left, int right) {
int len = right - left + 1;
//如果是01这种就不行
if (len > 1 && str.charAt(left) == '0') {
return false;
}
int res = 0;
while (left <= right) {
res = res * 10 + (str.charAt(left) - '0');
left++;
}
return res >= 0 && res <= 255;
}
public String multiply(String num1, String num2) {
if(num1.equals("0")||num2.equals("0")){
return "0";
}
char[] chars1 = num1.toCharArray();
char[] chars2 = num2.toCharArray();
//预分配空间,存储运算结果
int[] temp = new int[num1.length() + num2.length()];
//先不考虑进位问题,先将结果存放于临时数组中,把index=0的位置空出来,用于存放进位
for (int i = 0; i < chars1.length; i++) {
for (int j = 0; j < chars2.length; j++) {
temp[i + j + 1] += (chars1[i] - '0') * (chars2[j] - '0');
}
}
//从后往前进行进位处理
for (int i = temp.length - 1; i > 0; i--) {
if (temp[i] >= 10) {
//打个比方,如果是25,那temp[i]就变成5,让前置位+2
temp[i - 1] += temp[i] / 10;
temp[i] %= 10;
}
}
StringBuilder res = new StringBuilder();
for (int i : temp) {
res.append(i);
}
//如果前置位是0的话,就需要去掉0
if (res.charAt(0) == '0') {
res.deleteCharAt(0);
}
return res.toString();
}
String[] ver1 = version1.split("\\.");
String[] ver2 = version2.split("\\.");
int max = Math.max(ver1.length, ver2.length);
for (int i = 0; i < max; i++) {
int nums1;
int nums2;
if (i >= ver1.length) {
nums1 = 0;
} else {
nums1 = Integer.parseInt(ver1[i]);
}
if (i >= ver2.length) {
nums2 = 0;
} else {
nums2 = Integer.parseInt(ver2[i]);
}
if (nums1 == nums2) {
continue;
//此时version1>version2
} else if (nums1 > nums2) {
return 1;
} else {
return -1;
}
}
return 0;
//rand7()-1可以获取0、1、2、3、4、5、6
//*7后可以获取到0、7、14、21、28、35、42
//再加7可以获取到1、2、3、4、5、6、7
//然后再把二者相加获取1-10的数据
int num = (rand7() - 1) * 7 + rand7();
//如果当前数据>10,需要按照这个算法再次获取
while (num > 10) {
num = (rand7() - 1) * 7 + rand7();
}
return num;
public int widthOfBinaryTree(TreeNode root) {
Deque<TreeNode> queue = new LinkedList<>();
Deque<Integer> numQueue = new LinkedList<>();
queue.addLast(root);
numQueue.addLast(1);
while (!queue.isEmpty()) {
int size = queue.size();
int left = -1;
int right = -1;
int tempWidth = 0;
for (int i = 0; i < size; i++) {
TreeNode node = queue.pollFirst();
int position = numQueue.pollFirst();
if (i == 0) {
left = position;
}
if (i == size - 1) {
right = position;
}
if (node.left != null) {
queue.addLast(node.left);
numQueue.addLast(position * 2);
}
if (node.right != null) {
queue.addLast(node.right);
numQueue.addLast(position * 2 + 1);
}
}
tempWidth = right - left + 1;
res = Math.max(res, tempWidth);
}
return res;
}
Stack<Integer> stack = new Stack<>();
char[] chars = s.toCharArray();
int index = 0;
while (index < chars.length) {
//如果是空格的话就直接跳过
if (chars[index] == ' ') {
index++;
continue;
}
char temp = chars[index];
//如果是加减乘除的话,如果后面有空格就一直++,直到不是空格
if (temp == '+' || temp == '-' || temp == '*' || temp == '/') {
index++;
while (index < chars.length && chars[index] == ' ') {
index++;
}
}
int num = 0;
while (index < chars.length && Character.isDigit(chars[index])) {
num = num * 10 + (chars[index++] - '0');
}
if (temp == '-') {
num = -num;
} else if (temp == '*') {
num = stack.pop() * num;
} else if (temp == '/') {
num = stack.pop() / num;
}
stack.push(num);
}
int res = 0;
while (!stack.isEmpty()) {
res += stack.pop();
}
return res;
int m = mat.length;
int n = mat[0].length;
int[] res = new int[m * n];
int row = 0;
int col = 0;
for (int i = 0; i < res.length; i++) {
res[i] = mat[row][col];
//如果row+col%2==0的话,那就按右上方向走
if ((row + col) % 2 == 0) {
//如果列已到达最后一列,就需要往下走一格,否则会越界
if (col == mat[0].length - 1) {
row++;
//如果行的坐标是0的话,就往右走一格
} else if (row == 0) {
col++;
} else {
//其他情况,按照右上走
row--;
col++;
}
//如果row+col%2==1的话,那就按左下方向走
} else {
//如果行已到最后一行,就必须往右走了,否则会越界
if (row == mat.length - 1) {
col++;
//如果列的坐标是0的话,就往右走一格
} else if (col == 0) {
row++;
} else {
//其他情况,按照左下走
row++;
col--;
}
}
}
return res;
public String removeKdigits(String num, int k) {
char[] chars = num.toCharArray();
if (chars.length <= k) {
return "0";
}
//维护一个单调不下降的队列
Deque<Character>queue=new LinkedList<>();
for (int i = 0; i < chars.length; i++) {
char ch = chars[i];
//如果当前元素大于队列尾元素并且k>0,就弹出队列尾部元素
while (k > 0 && !queue.isEmpty() && ch < queue.peekLast()) {
k--;
queue.pollLast();
}
//如果是0123这种情况,0就不需要添加
if (i == 0 && ch == '0') {
continue;
//其他情况,加入队列中
} else {
queue.addLast(ch);
}
}
//如果此时k还大于0的话;比如123,k=1这种情况,那就需要弹出尾部元素
while (k>0&&!queue.isEmpty()){
queue.pollLast();
k--;
}
StringBuilder res = new StringBuilder();
//设置一个布尔标记为,如果队列首元素是0的话就continue
boolean flag=true;
while (!queue.isEmpty()) {
Character ch = queue.pollFirst();
if(flag&&ch=='0'){
continue;
}
flag=false;
res.append(ch);
}
if(res.length()==0){
return "0";
}
return res.toString();
}