24. 两两交换链表中的节点
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1);
ListNode cur = dummy, pre = head, tail = null;
cur.next = head;
while(pre!= null && pre.next!= null) {
tail = pre.next;
ListNode nextHead = tail.next;//临时存一下下剩下需要交换的链表
cur.next = tail;
tail.next = pre;
cur = cur.next.next;
pre = nextHead;
cur.next = nextHead;//连起剩下还没有交换的链表
}
return dummy.next;
}
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
for(ListNode pre = head, tail = null, cur = dummy; pre!= null && pre.next!= null;) {
tail = pre.next;
ListNode nextHead = tail.next;//临时存一下下剩下需要交换的链表
tail.next = pre;
pre.next = nextHead;
cur.next = tail;
cur = cur.next.next;
pre = nextHead;
}
return dummy.next;
}
}
25. K 个一组翻转链表
public class Solution {
//使用栈 Time:O(KN) Space:O(K)
//惨不忍睹运行效率
/**执行用时:
3 ms
, 在所有 Java 提交中击败了
7.28%
的用户
内存消耗:
41 MB
, 在所有 Java 提交中击败了
15.58%
的用户
*/
public ListNode reverseKGroup1(ListNode head, int k) {
ListNode p = head;
int len = 0;
while(p!=null){p=p.next; len++;}
if(len < k) return head;
Stack<ListNode> stack = new Stack<ListNode>();
len = k;
ListNode res = new ListNode(-1);
p = head;
ListNode cur = res;
while(p!=null){
len = k;
//入栈
while(p!=null && len >0){
len--;
stack.push(p);
p = p.next;
}
//足够k个
while(!stack.isEmpty()&&len==0){
cur.next = stack.pop();
cur = cur.next;
}
//不足k个
while(!stack.isEmpty()){
cur.next = stack.remove(0);
cur = cur.next;
}
}
cur.next = null; //注意最后一个要置为null
return res.next;
}
/**
执行用时:
0 ms
, 在所有 Java 提交中击败了
100.00%
的用户
内存消耗:
40.4 MB
, 在所有 Java 提交中击败了
32.27%
的用户
*/
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur = dummy;
while(true){
ListNode p = cur;
for(int i = 0; i < k && p!=null; i++) p = p.next;
if(p==null) break; //不够k个
//翻转 cur->a->b->c->d->e->f 那么p=d ==> 翻转k-1个cur->a<-b<-c<-d 剩下e->f
ListNode nextHead = p.next;//记录剩下还没有翻转链表e->f
ListNode a = cur.next, b = a.next;
for(int i = 0; i < k - 1; i++){
ListNode tmp = b.next; //记录还没有翻转的
b.next = a;
a = b;
b = tmp;
}
//cur->a<-b<-c<-d nextHead:e->f
//剩下几步: a->nextHead;cur->d; 变成cur->d->c->b->a->nextHead;更新cur=a(需要记录一下);
ListNode tmp = cur.next;//记录a
cur.next.next = nextHead;//a->nextHead
cur.next = a;//cur->d
cur = tmp;//更新cur=a
}
return dummy.next;
}
}
26. 删除有序数组中的重复项
class Solution {
public int removeDuplicates(int[] nums) {
int res = 0;
for(int i = 0; i < nums.length; i++){
if(i== 0 || nums[i]!= nums[i-1]){
nums[res++] = nums[i];;
}
}
return res;
}
}
27. 移除元素
class Solution {
public int removeElement(int[] nums, int val) {
int res = 0;
for(int i = 0; i < nums.length; i++) {
if(val == nums[i]) continue;
nums[res++] = nums[i];
}
return res;
}
}
28. 实现 strStr()
class Solution {
KMP算法 O(N)
public int strStr(String str, String pstr) {
if(pstr == null || pstr.length() == 0) return 0;
int sLen = str.length(), pLen = pstr.length();
if(sLen < pLen) return -1;//不够长罗
char s[] = new char[sLen + 1], p[] = new char[pLen + 1];
for(int i = 0; i< sLen; i++) s[i+1] = str.charAt(i);
for(int i = 0; i < pLen; i++) p[i+1] = pstr.charAt(i);
int ne[] = new int [50010];
//计算ne数组
for(int i = 2, j = 0; i <= pLen; i++) {
while(j > 0 && p[i] != p[j+1]) j = ne[j];
if(p[i] == p[j+1]) ++j;
ne[i] = j;
}
for(int i = 1, j = 0; i <= sLen; i++) {
while(j > 0 && s[i] != p[j+1]) j = ne[j];
if(s[i] == p[j+1]) ++j;
if(j == pLen) {
return i - j;
}
}
return -1;
}
}
29. 两数相除
class Solution {
/**
* x / y = k(1100101....) =>x = y * k(1100101....) =>x = y * 2^1 + y * 2^2+....y^k 快速幂的思想
*/
public int divide(int dividend, int divisor) {
if (dividend == 0) {
return 0;
}
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
if (dividend == Integer.MIN_VALUE && divisor == 1) {
return Integer.MIN_VALUE;
}
boolean isNegative = (dividend ^ divisor) < 0;
long _dividend = Math.abs((long)dividend);
long _divisor = Math.abs((long)divisor);
// System.out.println(_dividend + " " + _divisor);
int cnt = 0;
for (int i = 31; i >= 0; --i) {
if (_dividend >> i >= _divisor) {
cnt += 1 << i;
_dividend -= _divisor << i;
}
}
return isNegative ? -cnt : cnt;
}
public int divide(int dividend, int divisor) {
if(dividend == 0) return 0;
boolean isNegative = false;
if(dividend > 0 && divisor < 0 || dividend < 0 && divisor > 0) isNegative = true;
long a = (long) dividend, b = (long)divisor;
// long a = (long)Math.abs(dividend), b = (long) Math.abs(divisor); int abs有问题
if(a < 0) a = -a;
if(b < 0) b = -b;
List<Long> ep = new ArrayList<>();
for(long i = b; i <= a; i += i) {
ep.add(i);
}
long res = 0;
for(int i = ep.size() - 1; i >= 0; i--) {
if(a >= ep.get(i)) {
a -= ep.get(i);
res += (long)1 << i; //注意转换 如果是i是int 1 << i (31)时候 变为-2147483648
}
}
if(isNegative) res = -res;
if(res > 2147483647 || res < -2147483648) return 2147483647;
return (int)res;
}
}
30. 串联所有单词的子串
class Solution {
/**
* 滑动窗口
* 在s上维护一个滑动窗口
* @param s
* @param words
* @return
*/
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if(s == null || words == null || s.length() == 0 || words.length ==0)
return res;
int one_word = words[0].length();
int word_num = words.length;
int all_len = one_word * word_num;
HashMap<String,Integer> map = new HashMap<>();
for(String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for(int i = 0; i < one_word; i++) {
int left = i, right = i, count = 0;
HashMap<String, Integer> tmp_map = new HashMap<>();
while(right + one_word <= s.length()) {
String w = s.substring(right, right + one_word);
right = right + one_word;
if(!map.containsKey(w)) {
count = 0;
left = right;
tmp_map.clear();
}else {
tmp_map.put(w, tmp_map.getOrDefault(w, 0) + 1);
count++;
while(tmp_map.get(w) > map.get(w)) {
String t_w = s.substring(left, left + one_word);
count--;
tmp_map.put(t_w, tmp_map.getOrDefault(t_w, 0) - 1);
left += one_word;
}
if(count == word_num) res.add(left);
}
}
}
return res;
}
/**
* 方法一: 通过截取s字符串和words总字符长度相同的字符串,然后对截取的
* 字符串进行再次截取为单词,因为题目单词的长度相等,然后放入tmp_map中。
* words的字符串放入map中
* 对比map和tmp_map是否相等,相等就是s字符串的下表放入答案list中
* Space:O(N) Time:O(N^2)
* @param s
* @param words
* @return
*/
public List<Integer> findSubstring2(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if(s == null || words == null || s.length() == 0 || words.length ==0)
return res;
int one_word = words[0].length();
int word_num = words.length;
int all_len = one_word * word_num;
HashMap<String,Integer> map = new HashMap<>();
for(String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for(int i = 0; i < s.length() - all_len + 1; i++) {
String tmp = s.substring(i, i + all_len);
HashMap<String,Integer> tmp_map = new HashMap<>();
for(int j = 0; j < all_len; j+= one_word) {
String w = tmp.substring(j, j + one_word);
tmp_map.put(w, tmp_map.getOrDefault(w, 0) + 1);
}
if(map.equals(tmp_map)) res.add(i);
}
return res;
}
}