leetCode 66-70

234-回文链表

请判断一个链表是否为回文链表。

示例 1:
输入: 1->2->2->1
输出: true
示例 2:
输入: 1->2
输出: false

/**
 * 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) return true;

        //找到前半部分链表的尾结点,然后反转后半部分链表
        ListNode firstHalfEnd = endOfFirstHalf(head);
        //反转后半部分链表
        ListNode secondHalfStart = reverseList(firstHalfEnd.next);

        //判断是否是回文
        ListNode p1= head;
        ListNode p2 = secondHalfStart;
        //因为要返回原来的链表
        boolean result = true;
        //p2!=null 可以处理是奇数个的情况
        while(result&&p2!=null){
            if (p1.val != p2.val) {
                result = false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        firstHalfEnd.next = reverseList(secondHalfStart);
        return result;
    }

    //寻找中间节点
    private ListNode endOfFirstHalf(ListNode head){
        ListNode fast = head;
        ListNode slow = head;
        while(fast.next!=null&&fast.next.next!=null){
            fast = fast.next.next;
            slow = slow.next;
        }
        //1 2 3 2 1返回的是3     1 2 3 4 返回的是2
        return slow;
    }
    //反转链表
    private ListNode reverseList(ListNode head){
        //反转链表需要双指针,一个用来标记头结点,一个用来工作
        ListNode pre = new ListNode(0);
        ListNode cur = head;
        pre.next = null;
        while(cur!=null){
            cur = cur.next;
            head.next = pre.next;
            pre.next = head;
            head = cur;
        }
        return pre.next;
    }
}

236-二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>();
    Set<Integer> visited = new HashSet<Integer>();

    //深度遍历
    //在添加孩子节点时记录其父亲节点
    public void dfs(TreeNode root) {
        if (root.left != null) {
            //存放左孩子节点和root
            parent.put(root.left.val, root);
            dfs(root.left);
        }
        if (root.right != null) {
            //右孩子节点和root
            parent.put(root.right.val, root);
            dfs(root.right);
        }
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root);
        while (p != null) {
            //添加p节点以及其祖先结点
            visited.add(p.val);
            p = parent.get(p.val);
        }
        //遍历q的祖先节点,第一个在visited中出现的就是第一个公共祖先结点
        while (q != null) {
            if (visited.contains(q.val)) {
                return q;
            }
            q = parent.get(q.val);
        }
        return null;
    }
}

238. 除自身以外数组的乘积

给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:

输入: [1,2,3,4]
输出: [24,12,8,6]

class Solution {
    /**
      B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]-->B[i+1]=A[0]A[1]…*A[i]A[i+2]…*A[n-1]
      则:left[i+1]:A[0]A[1]…*A[i]    right[i+1]: A[i+2]…*A[n-1]
      则:left[i] = left[i-1]*A[i-1]  right[i] = right[i+1]*A[i+1]
     */
    public int[] productExceptSelf(int[] nums) {
        int[] B = new int[nums.length];
        B[0] = 1;
        //先求出左下角
        for(int i=1;i<nums.length;i++){
            B[i] = B[i-1]*nums[i-1];
        }
        int temp=1;
        for(int j=nums.length-1;j>=0;j--){
            B[j] = temp*B[j];
            //从右到左依次累积A[j],temp即是右下角
            temp = temp*nums[j];
        }
        return B;
    }
}

239-滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:

滑动窗口的位置      最大值
---------------               -----
[1 3 -1] -3 5 3 6 7       3
1 [3 -1 -3] 5 3 6 7       3
1 3 [-1 -3 5] 3 6 7       5
1 3 -1 [-3 5 3] 6 7       5
1 3 -1 -3 [5 3 6] 7       6
1 3 -1 -3 5 [3 6 7]       7

输入:nums = [1], k = 1 输出:[1] 示例 3:

输入:nums = [1,-1], k = 1 输出:[1,-1]

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] res = new int[nums.length-k+1];
        if(nums==null||nums.length==0||k<=0) return res;
        //双端队列 保存当前窗口最大值的数组位置 
        //保证队列中数组的数值从大到小
        Deque<Integer> queue = new LinkedList();

        for(int i=0;i<nums.length;i++){
        //依次把当前值和队列中最后一个值比较(队列存放的是数组中的下标)
        //比最后一个值大,则删除最后一个值,然后把当前值的下标放在队列最后
        //这个for循环的功能是找到当前窗口的最大值,并保存其他次大值
        //如 6 2 3 deque: 0 2    ;;; 如 6 3 2 deque : 0 1 2
            //依次与队尾比较,大于队尾则出队,找到更大的值,然后入队
            while(!queue.isEmpty()&&nums[i]>=nums[queue.peekLast()]){
                queue.pollLast();
            }
            //找到次大值。添加下标
            queue.addLast(i);
            //判断当前队列中队首的值是否有效(i-k即为窗口最左边的边界)
            if(queue.peekFirst()<=i-k){
                //无效则删除
                queue.pollFirst();
            }
            //当前窗口长度为k时,保存当前窗口最大值
            if(i+1>=k){
                res[i+1-k] = nums[queue.peekFirst()];
            }
        }
        return res;
    }
}

240. 搜索二维矩阵 II

在这里插入图片描述

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
       int row = 0;
       int cols =  matrix[0].length-1;
       while(row<matrix.length&&cols>=0){
           if(matrix[row][cols]>target){
               cols--;
           }else if(matrix[row][cols]<target){
               row++;
           }else{
               return true;
           }
       }
       return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值