Leecode——2021.04.19
27. 移除元素
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length;
for(int i = len - 1; i >= 0; i--){
if(nums[i] == val){
move(nums, i, len);
len--;
}
}
return len;
}
// 移动逻辑
public void move(int[] nums, int pos, int len){
for(int i = pos + 1; i < len; i++){
nums[i - 1] = nums[i];
}
}
}
双指针
26. 删除有序数组中的重复项
class Solution {
public int removeDuplicates(int[] nums) {
int left = 1;
int right = 1;
int n = nums.length;
if(n == 0 || n == 1){
return n;
}
int pre = nums[0];// 前一个点的位置
while(right < n){
if(nums[right] == pre){
right++;
}
else{
nums[left++] = nums[right];
pre = nums[right];
right++;
}
}
return left;
}
}
Leecode大神给出的对于删除重复项的通用解法。————k表示可以保留多少个重复的项
class Solution {
public int removeDuplicates(int[] nums) {
return process(nums, 1);
}
int process(int[] nums, int k) {
int idx = 0;
for (int x : nums) {
if (idx < k || nums[idx - k] != x) nums[idx++] = x;
}
return idx;
}
}
回文系列
面试题 01.04. 回文排列
class Solution {
public boolean canPermutePalindrome(String s) {
int n = s.length();
if(n == 0 || n == 1){
return true;
}
// 这个题不是给的就是回文串,而是将这个回文串打乱了,看这个给定的字符串是否由那个回文串打乱得到的
// 利用HashMap的方式
Map<Character, Integer>map = new HashMap<>();
for(int i = 0; i < n; i++){
int num = map.getOrDefault(s.charAt(i), 0);
map.put(s.charAt(i), num+1);
}
// 如果map集合里面的元素value值符合都是2的倍数或者说只有一个的value不是2的倍数那么就是回文串打乱来的
int cnt = 0;
for(Map.Entry<Character, Integer> entry: map.entrySet()){
if(entry.getValue() % 2 == 1){
cnt++;
}
}
if(cnt > 1){
return false;
}
else{
return true;
}
}
}
9. 回文数
给定一个正数,判断是否是一个回文数
// 反转部分字符串然后比较。从后往前截取
class Solution {
public boolean isPalindrome(int x) {
if(x < 0 || (x % 10 == 0 && x != 0)){
// 负数不可能是
// 120这种最后一位是0,但是不是0的不是回文数
return false;
}
int reverseNum = 0;
while(reverseNum < x){
reverseNum = reverseNum * 10 + x % 10;
x = x / 10;
// 不断的获取最后一位数,然后相加
}
// 分为了奇数和偶数两种情况
// eg:12321 这时候reverseNum = 123
return x == reverseNum || x == reverseNum / 10;
}
}
// 全部翻转。转化为String。利用StringBuilder来反转
class Solution {
public boolean isPalindrome(int x) {
if(x < 0){
return false;
}
String str = String.valueOf(x);
StringBuilder sb = new StringBuilder(str);
if(str.equals(sb.reverse().toString())){
return true;
}else{
return false;
}
}
}
125. 验证回文串
// 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
// 首位双指针法。碰到不是字母或者数字的跳过即可
class Solution {
public boolean isPalindrome(String s) {
// 将大写字母转化为小写字母
// 然后按照回文串来判断即可.注意一点就是,双指针碰到一个非字母或者数字的时候直接跳过
int n = s.length();
s = s.toLowerCase();// 转换为小写
int left = 0, right = n - 1;
while(left < right){
if( ( Character.isDigit(s.charAt(left)) ||
Character.isAlphabetic(s.charAt(left)) ) &&
( Character.isDigit(s.charAt(right)) ||
Character.isAlphabetic(s.charAt(right))
)
)
{
// left right所指向的字符是数字或者字母的时候才进行比较
if(s.charAt(left) == s.charAt(right)){
left++;
right--;
}else{
return false;
}
}
else if(
(Character.isDigit(s.charAt(left)) ||
Character.isAlphabetic(s.charAt(left)) ) &&
(!Character.isAlphabetic(s.charAt(right)) &&
!Character.isDigit(s.charAt(right))
)){
// 左边是数字或字母、右边不是
right--;
}
else if(
(Character.isDigit(s.charAt(right)) ||
Character.isAlphabetic(s.charAt(right)) ) &&
(!Character.isAlphabetic(s.charAt(left)) &&
!Character.isDigit(s.charAt(left))
)){
// 右边是数字或字母、左边不是
left++;
}
else{
// 都不是数字或者字母
left++;
right--;
}
}
return true;
}
}
234. 回文链表
// 高端做法:找到链表后半段的起点。反转后半段链表。然后和前半段链表比较。——Leeocde官方
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode firstHalfEnd = getFirstHalf(head);
ListNode afterreverseHalfStart = reverseList(firstHalfEnd.next);
// 比较两者是否是回文
ListNode pre = head;
ListNode end = afterreverseHalfStart;
boolean flag = true;
while(flag && end != null){
if(pre.val != end.val){
flag = false;
}
pre = pre.next;
end = end.next;
}
// 将链表转换为原来的结构
firstHalfEnd.next = reverseList(afterreverseHalfStart);
return flag;
}
// 反转链表
public ListNode reverseList(ListNode head){
ListNode s = head;
ListNode pre = null;
while(s != null){
ListNode tmp = s.next;
s.next = pre;
pre = s;
s = tmp;
}
return pre;
}
// 获取前半段链表的尾节点。
// 如果是奇数的话,中间节点是尾节点
public ListNode getFirstHalf(ListNode head) {
ListNode low = head;
ListNode high = head;
while(high.next != null && high.next.next != null){
// 如何找到。慢指针每次走一格。快指针走两个。当快指针走完的时候low正好指在前半段的末尾
low = low.next;
high = high.next.next;
}
return low;
}
}
// 暴力做法,利用数组或者字符串存储链表的val。然后就变成了基本的回文数的判断了