zoukankan      html  css  js  c++  java
  • 算法归类

    做题步骤


    1. 确定题型
    2. 搭框架
    3. 处理细节
    4. 思考边界测试条件

    1、双指针


    • 题眼:升/降序 数组 两数

    • 例题

      • lc 1 两数之和

        • 思路:第一想法是双指针,但是数组是无序的;再想哈希表,但是也是和两数相关的,一般要遍历的话,外层计数器i 即当成左边那个指针。

        • class Solution{
              public int[] twoSum(int[] nums,int target){
                  Map<Integer,Integer> hashtable = new HashMap<Integer,Integer>();
                  for(int i=0;i<nums.length;i++){
                      if(hashtable.containsKey(target-nums[i])){
                          return new int[]{hashtable.get(target-nums[i]),i};
                          //【要点1】Map自带get方法,键值对中,键是唯一的get(key)===>value
                          //【要点2】Map自带containsKey(key)方法,返回Boolean类型
                              //【要点2.1】后面用过Set之后发现,Set自带contains()方法
                          //【要点3】for( Map.Entry<> xxx : hashxxx.entrySet() )
                          //	hasxxx.entrySet() 里面才是getKey()、getValue()【用于包含键值对的for each遍历】
                      }else{
                          hashtable.put(nums[i],i);
                          //【要点4】因为从键得到值,所以要想要得到下标,要这样构建哈希表
                      }
                  }
              return new int[0];//【要点5】一定不要忘了,函数最后要有个返回值,这是函数的产出,就算随便写一个也行!
              }
          }
          
      • lc 141 环形链表

        • 思路:快慢指针判断环形链表,只要是环形,我一定能反追上

        • public class Solution {
              public boolean hasCycle(ListNode head) {
                  if (head == null || head.next == null) {  //aaa
                      return false;
                      //答案经常会这样写,因为测试用例有不少边界条件,直接先排除
                  }
                  ListNode slow = head;
                  ListNode fast = head.next;  //
                  while (slow != fast) {      //由于这个判断条件,fast要先行一步;
                                              //由于fast要先行一步,aaa处要多一个判断
                      if (fast == null || fast.next == null) {
                          return false;
                      }
                      slow = slow.next;
                      fast = fast.next.next;
               }
                  return true;
              }
          }
          
      • 881 救生艇

        • 思路:
    • 反思

      1. 要学习答案那样的代码书写方式!
      2. 哈希表最大的优点在于,键值对!另一个优点在于查找是否存在的速度比遍历快!
      3. 只有数组是有序排列的时候,对撞指针才最优
      4. 注意for each内不含索引!想要索引和对应的值,换成for(i=0;i<n;i++)
      5. int[] num .length 数组里面是属性,毕竟不是对象 // String a.length( )字符串里面是方法,毕竟人家是对象

    2、二分查找


    • 题眼:logN 升/降序 峰值

    • 例题

      • lc 704 二分查找

        • 思路:基本的二分查找,套用即可!

        • class Solution {
              public int search(int[] nums, int target) {
                  if(nums == null || nums.length == 0){
                      return -1;
                  }
                  int mid,left = 0;
                  int right = nums.length -1;
                  while(left <= right){
                      mid = left + (right - left) / 2;  //【要点1】这种一直要求的中间变量要放在while循环里,否则超时
                      if(nums[mid] == target){          //【要点2】为防止溢出 mid 这样求!
                          return mid;
                      }else if(nums[mid] < target){
                          left = mid +1;
                      }else
                          right = mid -1;
                  }
                  return -1;
              }
          }
          
      • 35

      • 162

      • 74

    • 反思:

    3、滑动窗口


    • 题眼:固定长度子串 数组

    • 例题:

      • lc 209 长度最小的子数组

        • class Solution {
              public int minSubArrayLen(int s, int[] nums) {
                  int n = nums.length;  //【要点1】排除边界:if(nums == null || nums.length == 0)
                  if (n == 0) {
                      return 0;
                  }
                  int ans = Integer.MAX_VALUE; //【要点2】这里取int最大值,是为看窗口滑到最后还没有找到>target的情况
                  int start = 0, end = 0;
                  int sum = 0;
                  while (end < n) {     //
                      sum += nums[end];
                      while (sum >= s) {  //【要点3】双层while,内部是为了找在满足的情况下是否还有更好的;my error
                          ans = Math.min(ans, end - start + 1);
                          sum -= nums[start];
                          start++;
                      }
                      end++;
                  }
                  return ans == Integer.MAX_VALUE ? 0 : ans;
              }
          }
          
      • 1456

        • 思路:滑动窗口、打擂台、哈希表--->哈希集合HashSet [a,e,i,o,u],比=='a' || =='b'.......快的多、暴力算法
      • 3

    • 反思

      1. 非定长也可能用滑动窗口!
      2. 第3 题中:
        1. 外层循环就是左指针!
        2. 当不知道right初值的时候,先不着急写
        3. 如果right指针实时移动的话,可能会在边界不符合的条件下,使得right多1【一个解决方法是,始终让right在要判断元素的左侧,另一个方法是后期计算窗口大小的时候-1(但是测试用例里有null,会报错)】

    4、递归


    • 例题
      • 509
      • 206
      • 344
    • 思路

    5、分治法


    • 例题
      • 209
      • 1456
    • 思路

    6、回溯法


    • 例题

    • 思路

    7、分治法


    • 例题
      • 209
      • 1456
    • 思路

    8、深度优先搜索DFS


    • 例题

    • 思路

    9、广度优先搜索BFS


    • 例题

    • 思路

    10、并查集


    • 例题

    • 思路

    11、贪心算法


    • 例题

    • 思路

    12、记忆化搜索


    • 例题

    • 思路

    13、动态规划DP


    • 例题
      • 509
      • 62
    • 思路
  • 相关阅读:
    String为值类型还是引用类型
    Mat数据类型
    各数据类型取值范围和所占字节数
    opencv matType
    python函数参数中冒号与箭头
    批量删除list中元素的方法
    PyQt QListview和QListWidgt
    函数形参中的冒号与箭头
    CSS选择器之相邻兄弟选择器
    CSS选择器之子元素选择器
  • 原文地址:https://www.cnblogs.com/petermaner/p/14515040.html
Copyright © 2011-2022 走看看