力扣Day17

234、回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

首先是考虑使用翻转链表,但是不行 (翻转代码如下:相当于自己又复习一遍翻转链表的力扣题)

class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode Next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=Next;
        }
       return pre.val==head.val;
    }
}

 首先是考虑使用翻转链表,但是不行

1:在进行翻转的时候,已经破坏了链表的结构了,此时实际就只有一个链表,是在原链表上反转的,那head最后指向反转后链表的尾部了,没办法往回遍历的

2:除非构建一个新表,将head的结构复制到新表上,在和翻转后的head表进行对比(建表有点麻烦,要ListNode res = new ListNode();//创建新的链表,之后每一次循环都要res.next=new ListNode(0);)

所以用翻转的思路进行修改 

注意:reverse的方法,所以要先把sb原先的值赋给别人再去翻转

法一:使用StringBuilder的reverse()

class Solution {
    public boolean isPalindrome(ListNode head) {
        //链表中节点数目在范围[1, 10^5] 内
        StringBuilder sb=new StringBuilder();
        ListNode temp=head;
        while(temp!=null){
            sb.append(temp.val);
            temp=temp.next;
        }
        String original=sb.toString(); 
        String reverse=sb.reverse().toString();
        return original.equals(reverse);
    }
}

知识回顾:equals与==的区别

==和equals在比较字符串时候的区别 - 菜鸟~风 - 博客园 (cnblogs.com)https://www.cnblogs.com/guoyafenghome/p/8542097.html#:~:text=%E7%BB%93%E8%AE%BA.%201%E3%80%81%3D%3D%E7%94%A8%E4%BA%8E%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E5%BC%95%E7%94%A8%E6%98%AF%E5%90%A6%E6%8C%87%E5%90%91%E5%90%8C%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%20equals%E7%94%A8%E4%BA%8E%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%90%A6%E7%9B%B8%E7%AD%89.%202%E3%80%81%E7%94%B1%E4%BA%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%89%B9%E6%AE%8A%20%E5%9C%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E6%B1%A0%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%3D%3D%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8equals%20%E6%8E%A8%E8%8D%90%E4%B8%8D%E7%AE%A1%E5%93%AA%E7%A7%8D%E6%96%B9%E5%BC%8F%20%E5%8F%AA%E8%A6%81%E6%98%AF%E6%AF%94%E8%BE%83%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B0%B1%E7%94%A8equals.%20%E5%88%86%E7%B1%BB%3A,%E8%8F%9C%E9%B8%9F~%E9%A3%8E.%20%E5%85%B3%E6%B3%A8%20-%200.%20%E7%B2%89%E4%B8%9D%20-%201.%20%2B%E5%8A%A0%E5%85%B3%E6%B3%A8.

1、首先的区别是,equals 是方法,而 == 是操作符;

2、== 只能用在8种基本数据类型

注意:字符串的常量池不属于堆、栈 

栈内存里面存放基本类型的变量和对象的引用变量

堆内存里面存放数组和new创建的对象。

法二:数组的方法:可以将结点的值添加到数组里,然后遍历数组判断回文————执行速度会比reverse的快

用数组的方法其实跟用list的方法一样。list.get(索引)来获取元素

class Solution {
    public boolean isPalindrome(ListNode head) {
        int len = 0;
        // 统计链表长度
        ListNode cur = head;
        while (cur != null) {
            len++;
            cur = cur.next;
        }
        cur = head;
        int[] res = new int[len];
        // 将元素加到数组之中
        for (int i = 0; i < res.length; i++){
            res[i] = cur.val;
            cur = cur.next;
        }
        // 比较回文
        for (int i = 0, j = len - 1; i < j; i++, j--){
            if (res[i] != res[j]){
                return false;
            }
        }
        return true;
    }
}

list集合的方法 

法三:1、链表的问题→双指针→快慢指针

          2、回文→翻转→因为全部翻转不行,那么就考虑将链表一分为二(保留头结点的结构不变,因为翻转后,要将题目的链表和翻转的链表进行对比,所以要保留题目的链表的头结点那一块的结构不变,才可以和翻转后的链表进行比较)

因为要将链表一分为二,所以要考虑链表的长度是奇数还是偶数:

链表中有四个结点,那么退出while循环: 快慢指针走了两次循环,即慢指针从结点1走到了结点3

链表中有五个结点,那么退出while循环: 快指针在链表的末尾结点,慢指针在链表的中间结点,这时候慢指针要额外走一步,慢指针就从结点1走到结点4,这样才可以判断前面两个结点和后面两个结点(中间的结点3不比较)

/**
 * 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) {
        //快慢指针  反转链表
        ListNode fast = head;
        ListNode slow = head;
        //快慢指针找中点 反转链表要分奇偶讨论
        while(fast != null && fast.next !=  null){
            fast = fast.next.next;
            slow = slow.next; 
        }
        
        if(fast != null){//链表长度是奇数的情况
            slow=slow.next;//奇数结点时 slow指向中间 此时slow+1 跟偶数统一 反转链表
        }
        slow = reverse(slow);
        fast = head;
        while(slow != null){//用slow!=null来当做循环条件
//是因为链表长度是奇数(5)时:一分为二的链表前面3个结点,后面2两个结点,
//只需判断前面的2个结点和后面的2个结点的值是否一样
//偶数就正常前面2个结点,后面2个结点判断。
            if(fast.val != slow.val)return false;
            fast = fast.next;
            slow = slow.next;
        }
        
        return true;
        
        
    }
    //实现反转链表方法
    ListNode reverse(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;    
        
    }
}

237、删除链表中的节点

请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。题目数据保证需要删除的节点 不是末尾节点 。

 分身!!

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 *     ListNode(){}
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        //只能访问以node开头的相关的结点
        node.val=node.next.val;
        node.next=node.next.next;
    }
}

549、最长和谐子序列

和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。

示例1:和谐数组可以有:[1, 2, 2, 2] 和  [2, 2, 2, 3, 3]   

/*  map.put(1,1);

    map.put(1,2);

    map.put(1,3);

    System.out.println(map.get(1));-----3  */

因为map里键不能重复,而值可以重复。所以如果有键重复的,那么他就会覆盖上一次的,即键若出现重复,则看最后一次的键和值才是真正的。

class Solution {
    //和谐数组里面的元素只有两个数但是可以重复
    // map<k,v> k:nums[i] v:出现重复元素的次数
    public int findLHS(int[] nums) {
        Map<Integer,Integer>map=new HashMap<>();
        int maxLength=0;
        //记录数组元素以及他们的次数
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(nums[i])){
                map.put(nums[i],map.get(nums[i])+1);
            }else{
                map.put(nums[i],1);
            }
        }
        //判断是否有元素1 +1 即元素2的存在,如果有,那么和谐数组的长度就是1的出现的次数+2出现的次数
        //有点动态规划?
        for(int i:map.keySet()){
            if(map.containsKey(i+1)){
                maxLength=Math.max(maxLength,map.get(i)+map.get(i+1));
            }
        }
        return maxLength;
        
    }
   
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值