基本算法学习day1

数组和字符串

反转数组
  • 采用俩个指针,分别指向头和尾。移动进行交换
  • 下标查找的时间复杂度是O1
  • 查询是否存在的时间复杂度On

leecode242. 有效的字母异位词
方法:
创建26位的int数组,用来存放对应第几个字母的个数
遍历 s让相应的值++ ,遍历 t让相应的值 - -
最后如果数组中有一个值不为0则返回false

//给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 
//
// 示例 1: 
//
// 输入: s = "anagram", t = "nagaram"
//输出: true
// 
//
// 示例 2: 
//
// 输入: s = "rat", t = "car"
//输出: false 
//
// 说明: 
//你可以假设字符串只包含小写字母。 
class Solution {
    public boolean isAnagram(String s, String t) {
        //用来存放string中26个英文字母的数量
        int[] num=new int[26];
        char[] chars=s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            num[chars[i]-'a']++;
        }
        char[] chars1 = t.toCharArray();
        for (int i = 0; i < chars1.length; i++) {
            num[chars1[i]-'a']--;
        }
        for (int i = 0; i < num.length; i++) {
            if(num[i]!=0) return false;
        }
        return true;
    }
}

链表

  • 灵活的分配内存空间
  • 前一个元素已知,能在O1时间内删除或添加元素
  • 链表不能快速查询,查询元素需要On的时间
结题技巧
  1. 利用快慢指针,有时候需要用到三个指针
    链表的反转,寻找倒数第k个元素,判断链表是否有环
  2. 构建一个虚假的链表头
    给定排好序的链表,将他们整合 并且排序
    将链表的奇偶数按原定顺序分离,生成前半部分为奇数,后半部分为偶数的链表
    在解决链表的题目时,在纸上或者白板上画出节点之间的相互关系
    leecode25. K个一组翻转链表
    方法:
    用三个指针,前指针,当前指针,下一个指针
    开始前指针指向第一个指针的上一个,当前指针和下一个指针遍历,进行翻转,结束后,下一个指针指向了下一个K的头,当前指针(原来的尾,现在的头)与前指针相连,原来的头(现在的尾)与下一个指针相连。
    继续遍历下一个K。
//给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。 
//
// k 是一个正整数,它的值小于或等于链表的长度。 
//
// 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 
//
// 
//
// 示例: 
//
// 给你这个链表:1->2->3->4->5 
//
// 当 k = 2 时,应当返回: 2->1->4->3->5 
//
// 当 k = 3 时,应当返回: 3->2->1->4->5 
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode pre=dummy;//表示头节点
        ListNode now=head;//表示当前节点
        ListNode next=head;//表示下一个的头节点
        ListNode end=dummy;//表示最后一个节点
        while(end!=null){
            for (int i = 0; i <k && end!=null; i++) end=end.next;
            if(end==null) break;// end为空,则长度不够,不反转
            next=end.next;//存下一个的头
            end.next=null;//让尾巴的下一个节点等于null
            reserve(now);
            pre.next=end;
            now.next=next;
            pre=now;
            end=now;
            now=next;
        }
        return dummy.next;
    }
    void reserve(ListNode now){
        ListNode next=null;
        ListNode temp=new ListNode(0);
        while (now!=null){
            next=now.next;
            now.next=temp;
            temp=now;
            now=next;
        }
    }
}

  • 后进先出,只能操作栈顶
  • 当在解决某个问题的时候,只关心最近一次的操作,并且在处理完上一次操作后,能在O1时间内查找到更前一次的操作
    leecode20.有效的括号
    方法:
    不断的压入左括号,遇到相应的右括号则弹出。如果最后栈为空,则正确,否则错误
    leecode739.每日温度
    方法:
    用栈来进行操作,将值存在数组中。栈中存放的元素除了值以外还得存下标。所以存Entry
    当遇到比栈顶温度低的,存入栈顶
    while(当遇到比栈顶温度高时) { 吐出栈顶,对应下标的值为 当前下标减去栈顶下标 }
//请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
// 
//
// 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2
//, 1, 1, 0, 0]。 
class Solution {
    class Entry{
        int value;
        int index;
        public Entry(int value,int index){
            this.value=value;
            this.index=index;
        }
    }
    public int[] dailyTemperatures(int[] T) {
        int len=T.length;
        if(len==0) return null;
        int[] result=new int[len];
        Stack<Entry> stack=new Stack<>();
        stack.push(new Entry(T[0], 0));
        for (int i = 1; i <len ; i++) {
            while (!stack.isEmpty() && stack.peek().value < T[i]) {
                result[stack.peek().index] =i-stack.peek().index;
                stack.pop();
            }
            stack.push(new Entry(T[i],i));
        }
        return result;
    }
}

队列

  • 先进先出 用LinkedList实现
  • 常用场景:广度优先遍历
双端队列
  • LInkedList实现,需要对队列的头尾俩端能在O1的时间内进数据的操作
  • 实现一个长度动态变化的窗口或者连续区间
    leecode239.滑动窗口最大值
    实现:
    利用双端队列来表示这个窗口,用List存返回的列表
    先全部添加到窗口中,添加时,while(下一个元素比链表的尾大) {把前面尾删了},再把下一个元素加入进去。
    因为在没移动前就需要增加当前的最大值,所以list先增加一下链表的头
    移动:添加的时候:while(下一个元素比链表的尾大) {把前面尾删了}, 如果移动的时候queue.getFirst()==nums[i-k]则删除双端链表的头,再把下一个元素加入进去。list增加链表的头
    到底后,把list返回
//给定一个数组 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 
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        LinkedList<Integer> queue=new LinkedList<>();
        ArrayList<Integer> result=new ArrayList<>();
        for (int i = 0; i <k ; i++) {
            if(i==0) {
                queue.add(nums[0]);
                continue;
            }
            while (!queue.isEmpty() && queue.getLast()<nums[i]){
                queue.removeLast();
            }
            queue.add(nums[i]);
        }
        result.add(queue.getFirst());
        for (int i = k; i <nums.length ; i++) {
            while (!queue.isEmpty() && queue.getLast()<nums[i]){
                queue.removeLast();
            }
            queue.add(nums[i]);
            if(queue.getFirst()==nums[i-k]) queue.removeFirst();
            result.add(queue.getFirst());
        }
        int[] rr=new int[result.size()];
        for (int i = 0; i <rr.length ; i++) {
            rr[i]=result.get(i);
        }
        return rr;
    }
 }

  • 树有前序中序和后序。可以调用递归
  • 平衡二叉树
  • 完全二叉树
  • 二叉搜索树
  • 四叉树
    遍历:
  • 中序遍历是顺序的
  • leecode250 必须得看
void toArray(TreeNode root,List<Integer> list){
        if(root==null) return;
        toArray(root.left,list);
        list.add(root.val); //添加在中间是中序,添加在前面是前序,添加在后面是后序
        toArray(root.right,list);
    }

leecode230.二叉搜索中第K小的元素
方法:
二叉树中序遍历,添加到list中 返回第k-1个元素
如果这道题变成了 搜索第K大的元素:则将其变成了反向的中序遍历:右 ;add();左;

//给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。 
//
// 说明: 
//你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。 
//
// 示例 1: 
//
// 输入: root = [3,1,4,null,2], k = 1
//   3
//  / \
// 1   4
//  \
//   2
//输出: 1 

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        List<Integer> list=new ArrayList<>();
        toArray(root, list);
        return list.get(k-1);
    }
    void toArray(TreeNode root,List<Integer> list){
        if(root==null) return;
        toArray(root.left,list);
        list.add(root.val);
        toArray(root.right,list);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值