昨天写博客写的太晚没睡好,早上有周赛有不敢睡多怕错过,导致今天一天迷迷瞪瞪,周赛的成绩也不理想,题目没看清吃了罚时;下周双周赛和周赛见吧。
参加了个力扣的刷题pk,明天开始,我在假装摆烂堆,凑凑热闹吧;
发现边界条件总是判断不太好,边界多了if else不好看,大佬们写的都很优雅,想不到的点
今日刷题
17. 电话号码的字母组合 经典回溯
开始找几个双指针的题刷下
public int removeElement(int[] nums, int val) {
int left = 0;
for(int fast=0;fast<nums.length;fast++){
if(nums[fast]!=val){
nums[left++] = nums[fast];
}
}
return left;
}
public void reverseString(char[] s) {
int left = 0;
int right = s.length-1;
while(left<right){
s[left]^=s[right];
s[right]^=s[left];
s[left++]^=s[right--];
}
}
public String replaceSpace(String s) {
String res = "";
for(int i=0;i<s.length();i++){
if(s.charAt(i)==' '){
res+="%20";
}else{
res+=s.charAt(i);
}
}
return res;
}
双指针,从后往前滑动, 思路 1 计算原始字符串s中有多少个空串
2 设置左指针为原始字符串的最后一个字符的index,记为left;
3 拼接1中计算的 3倍空串(拼接两个)到后边
4 右指针为拼接后的最后一个index,记为循环参数right;
5 计算左指针字符串数组是否为空串
6 如果是空串,右指针往前移动3个位置,并拼接%20;
7如果不是,赋值右==左;
没有使用额外空间
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for(int i=0;i<s.length();i++){
if(s.charAt(i)==' '){
sb.append(" ");
}
}
int left = s.length()-1;
s+=sb.toString();
char[] arr = s.toCharArray();
for(int right=s.length()-1;right>0;right--){
if(arr[left]==' '){
arr[right--] = '0';
arr[right--] = '2';
arr[right] = '%';
}else{
arr[right] = arr[left];
}
left--;
}
return new String(arr);
}
19. 删除链表的倒数第 N 个结点 思路:快慢指针,快指针指先走n; 然后快慢指针一起向后滑动,留一个pre=slow方便最后操作指针
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode pre = dummy;
ListNode fast = dummy;
ListNode slow = dummy;
for(int i=0;i<n;i++){
fast = fast.next;
}
while(fast!=null){
pre = slow;
slow = slow.next;
fast = fast.next;
}
pre.next = pre.next.next;
return dummy.next;
}
15. 三数之和 思路:排序,双指针,O^3优化为O^2;
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
if(nums[i]>0)return res;
if(i>0&&nums[i]==nums[i-1])continue;
int k = i+1;
int j = nums.length-1;
while(k<j){
if(nums[i]+nums[k]+nums[j]>0){
j--;
}else if(nums[i]+nums[k]+nums[j]<0){
k++;
}else{
res.add(Arrays.asList(nums[i],nums[j],nums[k]));
while(k<j&&nums[k]==nums[k+1])k++;
while(k<j&&nums[j]==nums[j-1])j--;
k++;
j--;
}
}
}
return res;
}
双指针就刷到这里, 下边刷栈与队列
先写下思路吧: 队列fifo,栈filo; 用两个栈模拟队列,一个inStack,一个outStack;
class MyQueue {
Stack<Integer> inStack;
Stack<Integer> outStack;
public MyQueue() {
inStack = new Stack<>();
outStack = new Stack<>();
}
public void push(int x) {
inStack.push(x);
}
public int pop() {
if(!outStack.isEmpty()){
return outStack.pop();
}
while(!inStack.isEmpty()){
outStack.push(inStack.pop());
}
return outStack.pop();
}
public int peek() {
if(!outStack.isEmpty()){
return outStack.peek();
}
while(!inStack.isEmpty()){
outStack.push(inStack.pop());
}
return outStack.peek();
}
public boolean empty() {
return inStack.empty()&&outStack.empty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/