• 简单算法2


    二分查找

    package com.sly.uploadfile.algorithm.pack1;
    
    import java.util.Arrays;
    
    /**
     * Created by fmgao on 2019/9/25.
     * <p>
     * Java语言二分查找代码实现
     */
    public class ErFenChaZhao {
    
        /**
         * 二分查找key值对应的下标
         *
         * @param source 输入的源数组 ,请保证为一个有序数组
         * @param key    需要查找的值
         * @return 正数为查找到的坐标,-1表示没有查到
         */
        public static int binarySearch(int[] source, int key) {
            int low = 0;
            int high = source.length - 1;
            while (low <= high) {
                int mid = (low + high) >>> 1; //使用位移运算法高效地获取折中下标,这里不考虑符号,所以使用>>>
                int midVal = source[mid];
                if (midVal < key) {
                    low = mid + 1;
                } else if (midVal > key) {
                    high = mid - 1;
                } else
                    return mid;
            }
            return -1;
        }
    
        public static void main(String[] args) {
            int[] source = new int[]{12, 213, 232, 343, 123, -1, 123, 232424, 1253, 56, 456, 234, -2342};
            //保证数组为有序数组
            Arrays.sort(source);
            //打印排序后的数组元素
            System.out.print("Sorted Source : ");
            for (int i = 0; i < source.length; i++) {
                System.out.print(source[i] + " ");
            }
            System.out.println();
            System.out.println(binarySearch(source, 56));
        }
    
    }

    俩数相加

    package com.sly.uploadfile.algorithm.twoadd;
    
    /**
     * Created by fmgao on 2019/11/13.
     * <p>
     * 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,
     * 并且它们的每个节点只能存储 一位 数字。
     * <p>
     * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
     * <p>
     * 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
     * <p>
     * 示例:
     * <p>
     * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
     * 输出:7 -> 0 -> 8
     * 原因:342 + 465 = 807
     */
    public class TwoAdd {
    
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            ListNode dumpHead = new ListNode(0);
            ListNode p = l1, q = l2, curr = dumpHead;
            int carry = 0;
            while (p != null || q != null) {
                int x = (p != null) ? p.data : 0;
                int y = (q != null) ? q.data : 0;
                int sum = x + y + carry;
                carry = sum / 10;
    
                curr.next = new ListNode(sum % 10);
                curr = curr.next;
                if (p != null) p = p.next;
                if (q != null) q = q.next;
            }
            if (carry != 0) {
                curr.next = new ListNode(carry);
            }
            return dumpHead.next;
        }
    
    
        public static void main(String[] args) {
            SingleLinkedList l1 = new SingleLinkedList();
            l1.addData(1);
            l1.addData(2);
            l1.addData(5);
            SingleLinkedList l2 = new SingleLinkedList();
            l2.addData(3);
            l2.addData(2);
            l2.addData(7);
            TwoAdd solution = new TwoAdd();
            ListNode l3 = solution.addTwoNumbers(l1.head, l2.head);
            while (l3 != null) {
                if (l3.next == null) {
                    System.out.print(l3.data);
                    l3 = l3.next;
                } else {
                    System.out.print(l3.data + "->");
                    l3 = l3.next;
                }
            }
            System.out.println();
            System.out.println("/:" + 25 / 10);
            System.out.println("%:" + 25 % 10);
        }
    }

    俩数相加

    package com.sly.uploadfile.algorithm.twoadd;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by fmgao on 2019/12/30.
     */
    public class TwoNum {
    
    
        public static void main(String[] args) {
            int[] nums = {2, 7, 11, 15};
            int tar = 22;
            int[] ints = twoNum(nums, tar);
            for (int s : ints) {
                System.out.println(s);
            }
        }
    
        public static int[] twoNum(int[] nums, int target) {
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                int com = target - nums[i];
                if (map.containsKey(com)) {
                    return new int[]{map.get(com), i};
                } else {
                    map.put(nums[i], i);
                }
            }
            throw new IllegalArgumentException("No two sum solution");
        }
    
    }

    是否有重复元素

    package com.sly.uploadfile.algorithm;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by fmgao on 2019/9/27.
     * <p>
     * [Leetcode] 220. 存在重复元素 II java
     * <p>
     * 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,
     * 使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。
     * <p>
     * Example 1:
     * <p>
     * Input: nums = [1,2,3,1], k = 3, t = 0
     * Output: true
     * <p>
     * Example 2:
     * <p>
     * Input: nums = [1,0,1,1], k = 1, t = 2
     * Output: true
     * <p>
     * Example 3:
     * <p>
     * Input: nums = [1,5,9,1,5,9], k = 2, t = 3
     * Output: false
     */
    public class ContainsNearByDuplicate {
        public static void main(String[] args) {
            int[] nu = {1, 2, 3, 1};
            boolean b = containsNearByAlmostDuplicate(nu, 21, 1);
            System.out.println(b);
        }
    
        public static boolean containsNearByAlmostDuplicate(int[] a, int k, int t) {
    //        if (k < 1 || t < 0 || nums == null || nums.length < 2) {
    //            return false;
    //        }
    //        SortedSet<Long> set = new TreeSet<>();
    //        for (int j = 0; j < nums.length; j++) {
    //            SortedSet<Long> subset = set.subSet((long) nums[j] - t, (long) nums[j] + t + 1);
    //            if (!subset.isEmpty()) {
    //                return true;
    //            }
    //            if (j >= k) {
    //                set.remove((long) nums[j - k]);
    //            }
    //            set.add((long) nums[j]);
    //        }
    //        for (Long ss : set) {
    //            System.out.println(ss);
    //        }
    
            /**
             * 给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。
    
             示例 1:
    
             输入: nums = [1,2,3,1], k = 3
             输出: true
    
             示例 2:
    
             输入: nums = [1,0,1,1], k = 1
             输出: true
    
             示例 3:
    
             输入: nums = [1,2,3,1,2,3], k = 2
             输出: false
             */
    
            // (双指针法,快慢指针加了一个限定(Math.abs ( i-j )<=k),相当于滑动窗口(有滑动限定))+map存储元素
            int j;
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < a.length; i++) {
                //   当map中存在数组元素时,证明两个元素相同
                if (map.containsKey(a[i])) {
                    //   让j等于map中与数组元素相等的那个键对应值
                    j = map.get(a[i]);
                    //   判断新的这个(遍历后的)索引和Map中的索引的差是否小于k,小于则输出true。
                    if (Math.abs(i - j) <= k) {
                        System.out.println("true");
                    }
                    //将新的索引值添加到map中
                    map.put(a[i], i);
                } else {
                    // 向map中添加元素
                    map.put(a[i], i);
                }
            }
            System.out.println("false");
            return false;
        }
    
    }

    数字1的个数

    package com.sly.uploadfile.algorithm;

    /**
     * Created by fmgao on 2019/9/29.
     * <p>
     * [LeetCode] Number of Digit One 数字1的个数
     * Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
     * For example:
     * Given n = 13,
     * Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
     */

    /**
     《编程之美》上这样说:

     设N = abcde ,其中abcde分别为十进制中各位上的数字。

     如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。

     如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,
     则可以知道百位出现1的情况可能是:100~199,1100~1199,2100~2199,,...,11100~11199,一共1200个。
     可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。注意:高位数字不包括当前位

     如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,
     则可以知道百位受高位影响出现的情况是:100~199,1100~1199,2100~2199,,....,11100~11199,一共1200个。
     和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。
     但同时它还受低位影响,百位出现1的情况是:12100~12113,一共14个,等于低位数字(13)+1。 注意:低位数字不包括当前数字

     如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,比如12213,
     则百位出现1的情况是:100~199,1100~1199,2100~2199,...,11100~11199,12100~12199,一共有1300个,
     并且等于更高位数字+1(12+1)乘以当前位数(100)
     */
    public class CountDigitOne {

        public static void main(String[] args) {
            int a = 27;
            int i = countDigitOne(a);
            System.out.println(i);
        }

        public static int countDigitOne(int n) {
            if (n < 1) {
                return 0;
            }
            int res = 0;
            long i = 1;
            while (n >= i) {
                res += (n / i + 8) / 10 * i + ((n / i) % 10 == 1 ? (n % i + 1) : 0);
                i *= 10;
            }
            return res;
        }
    }

    package com.sly.uploadfile.algorithm;

    /**
     * Created by fmgao on 2019/9/29.
     */
    public class CountDigitOne2 {
        public static void main(String[] args) {
            int a = 27;
            int i = countDigitOne(a);
            System.out.println(i);
        }

        public static int countDigitOne(int n) {
            if (n <= 0) {
                return 0;
            }
            String stringN = n + "";
            int ans = 0;
            while (!stringN.isEmpty()) {
                int tempLen = stringN.length();
                String firstChar = stringN.charAt(0) + "";
                if (Integer.parseInt(firstChar) >= 2) {
                    ans += 1 * Math.pow(10, tempLen - 1);
                } else if (firstChar.equals("1")) {
                    if ("".equals(stringN.substring(1, tempLen))) {
                        ans += 1;
                    } else if (!"".equals(stringN.substring(1, tempLen))) {
                        ans += Integer.parseInt(stringN.substring(1, tempLen)) + 1;
                    }
                }
                if (tempLen > 1) {
                    ans += Integer.parseInt(firstChar) * (tempLen - 1) * Math.pow(10, tempLen - 2);
                }
                stringN = stringN.substring(1);
            }
            return ans;
        }
    }


    被除数与除数

    package com.sly.uploadfile.algorithm;
    
    /**
     * Created by fmgao on 2019/7/9.
     *
     * 给定两个整数,被除数 dividend和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
     * 返回被除数 dividend除以除数 divisor得到的商。
     */
    public class Divide01 {
        public static int divide(int dividend, int divisor) {
            if (divisor == 0 || (dividend == Integer.MIN_VALUE && divisor == -1)) {
                return Integer.MAX_VALUE;
            }
            int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1;// 异或运算
            long ms = (long) dividend;
            long ns = (long) divisor;
            ms = Math.abs(ms);
            ns = Math.abs(ns);
            int num = 0;
            while (ms >= ns) {
                long m = ns;
                long n = 1;
                while (ms >= (m << 1)) {
                    m <<= 1;
                    n <<= 1;
    
                }
                num += n;
                ms -= m;
    
            }
            return num * sign;
        }
    
        public static void main(String[] args) {
            int a = divide(46, 3);
            System.out.println(a);
        }
    }

    数字异或

    package com.sly.uploadfile.algorithm;
    
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by fmgao on 2019/6/24.
     * <p>
     * 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
     * <p>
     * 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
     * <p>
     * Example 1:
     * <p>
     * Input:
     * s: "cbaebabacd" p: "abc"
     * <p>
     * Output:
     * [0, 6]
     * <p>
     * Explanation:
     * The substring with start index = 0 is "cba", which is an anagram of "abc".
     * The substring with start index = 6 is "bac", which is an anagram of "abc".
     * <p>
     * Example 2:
     * <p>
     * Input:
     * s: "abab" p: "ab"
     * <p>
     * Output:
     * [0, 1, 2]
     * <p>
     * Explanation:
     * The substring with start index = 0 is "ab", which is an anagram of "ab".
     * The substring with start index = 1 is "ba", which is an anagram of "ab".
     * The substring with start index = 2 is "ab", which is an anagram of "ab".
     */
    @Slf4j
    public class EctopicElementService {
        public static List<Integer> findAnagrams(String s, String p) {
            List<Integer> list = new ArrayList<>();
            int lens = s.length();
            int lenp = p.length();
            if (lens < lenp) {
                return list;
            }
            for (int i = 0; i <= lens - lenp; i++) {
                int[] t = new int[26];
                for (int j = 0; j < lenp; j++) {
                    t[s.charAt(i + j) - 'a']++;
                    t[p.charAt(j) - 'a']--;
                }
                boolean flag = true;
                for (int j = 0; j < t.length; j++) {
                    if (t[j] != 0) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    list.add(i);
                }
            }
    //        log.info("list====" + list);
            return list;
        }
    
        public static void main(String[] args) {
            List<Integer> anagrams = findAnagrams("cbaebabacd", "abc");
            System.out.println(anagrams);
        }
    }

     

    括号成对校验

    package com.sly.uploadfile.algorithm;
    
    import java.util.Stack;
    
    /**
     * Created by fmgao on 2019/6/28.
     */
    public class EffectiveParentheses {
        public static boolean isValid(String s) {
            if (s == "" || s.length() == 0) {
                return true;
            }
            Stack stack = new Stack();
            stack.push(s.charAt(0));
            for (int i = 1; i < s.length(); i++) {
                if (!stack.isEmpty()) {
                    if (stack.peek().equals((char) (s.charAt(i) - 1)) || stack.peek().equals((char) (s.charAt(i) - 2))) {
                        stack.pop();
                    } else {
                        stack.push(s.charAt(i));
                    }
                } else {
                    stack.push(s.charAt(i));
                }
            }
            if (stack.isEmpty()) {
                return true;
            }
            return false;
        }
    
        public static boolean isValid2(String s) {
            Stack<Character> stack = new Stack<>();
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if (ch == '(' || ch == '[' || ch == '{') {
                    stack.push(ch);
                } else {
                    if (stack.isEmpty()) {
                        return false;
                    }
                    char topChar = stack.pop();
                    if (ch == ')' && topChar != '(') {
                        return false;
                    } else if (ch == ']' && topChar != '[') {
                        return false;
                    } else if (ch == '}' && topChar != '{') {
                        return false;
                    }
                }
            }
            return stack.isEmpty();
        }
    
        public static void main(String[] args) {
            long startTime = System.nanoTime();
            boolean res = isValid("()(){}{}(){}()[][]{}");
            long endTime = System.nanoTime();
            System.out.println(res);
            System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
    
            long startTime2 = System.nanoTime();
            boolean res2 = isValid2("()(){}{}(){}()[][]{}");
            long endTime2 = System.nanoTime();
            System.out.println(res2);
            System.out.println("程序运行时间: " + (endTime2 - startTime2) + "ms");
        }
    }

    找俩个子串拼接位置

    package com.sly.uploadfile.algorithm;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    /**
     * Created by fmgao on 2019/7/3.
     */
    public class FindSonChars {
    
        public static void main(String[] args) {
            String s = "barfoothefoobarman";
            String[] words = {"foo", "bar"};
            FindSonChars findSonChars = new FindSonChars();
            List<Integer> list = findSonChars.findSubstring(s, words);
            for (Integer a : list) {
                System.out.println(a);
            }
    
        }
    
        /**
         * 1、 字符串和数组都是空  就return 空数组
         * 2、
         *
         * @param s
         * @param words
         * @return
         */
        public List<Integer> findSubstring(String s, String[] words) {
            List<Integer> result = new ArrayList<Integer>();
            // 如果s,或者是words为空,那么也返回一个空的列表
            if (s.length() == 0 || s == null || words.length == 0 || words == null) {
                return result;
    
            }
            int size = words[0].length(), length = words.length;
            // 把字符串数组中的的字符串全部插入HashMap中
            HashMap<String, Integer> map = generate(words);
            // 窗口的不同的起点,有size个不同的起点
            for (int i = 0; i < size; i++) {
                HashMap<String, Integer> window = new HashMap<>();  // 一个滑动的窗口
                int left, right;
                left = right = i;
                while (right <= s.length() - size && left <= s.length() - length * size) {
                    String word = s.substring(right, right + size);
                    incr(window, word);
                    if (!map.containsKey(word)) {
                        window.clear();
                        right += size;
                        left = right;
                        continue;
                    }
                    while (window.get(word) > map.get(word)) {
                        String w = s.substring(left, left + size);
                        decr(window, w);
                        left += size;
                    }
                    right += size;
                    if (right - left == size * length) {
                        result.add(left);
                    }
                }
            }
            return result;
    
        }
    
        private HashMap<String, Integer> generate(String[] strs) {
            HashMap<String, Integer> map = new HashMap<>();
            for (String str : strs) {
                incr(map, str);
            }
            return map;
        }
    
        private void incr(HashMap<String, Integer> map, String str) {
            map.put(str, map.getOrDefault(str, 0) + 1);
        }
    
        private void decr(HashMap<String, Integer> map, String str) {
            Integer num = map.get(str);
            if (num <= 1) {
                map.remove(str);
            } else {
                map.put(str, num - 1);
            }
        }
    }

    二分查找升级版

    package com.sly.uploadfile.algorithm;
    
    /**
     * Created by fmgao on 2019/11/19.
     * <p>
     * 力扣算法】34-在排序数组中查找元素的第一个和最后一个位置
     * 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
     * <p>
     * 你的算法时间复杂度必须是 O(log n) 级别。
     * <p>
     * 如果数组中不存在目标值,返回 [-1, -1]。
     * <p>
     * 示例 1:
     * 输入: nums = [5,7,7,8,8,10], target = 8
     * 输出: [3,4]
     * 示例 2:
     * 输入: nums = [5,7,7,8,8,10], target = 6
     * 输出: [-1,-1]
     */
    public class FirstLastSortArray {
    
        public static void main(String[] args) {
            int[] nums = {5, 7, 8, 8, 8, 10};
            int target = 8;
            int[] ints = searchSort2(nums, target);
            for (int i : ints) {
                System.out.println(i);
            }
        }
    
        /**
         * 二分查找的升级版。以searchBegin为例,
         * <p>
         * 当nums[mid]>target时,向左查找,
         * 当nums[mid]=targe时,向左查找。
         * 这样所有情况下,范围都会缩小,直到 l == r 为止,这时如果 该位置里的数 == target,则返回该位置,否则返回-1。
         * <p>
         * searchEnd同理
         *
         * @param nums
         * @param target
         * @return
         */
        public static int[] searchSort2(int[] nums, int target) {
            if (nums == null || nums.length == 0) {
                return new int[]{-1, -1};
            }
            int l = 0, r = nums.length;
            int mid = (l + r) / 2;
            int p = -1;
            while (l < r) {
                // 中间
                if (nums[mid] == target) {
                    p = mid;
                    break;
                }
                // target 在左边
                if (nums[mid] > target) {
                    if (r == mid) break;
                    r = mid;
                    mid = (l + r) / 2;
                } else {
                    // 在右边
                    if (l == mid) break;
                    l = mid;
                    mid = (l + r) / 2;
                }
            }
            if (p == -1) {
                return new int[]{-1, -1};
            } else {
                int a = p, b = p;
                while (a > 0 && nums[a - 1] == target) a--;
                while (b < nums.length - 1 && nums[b + 1] == target) b++;
                return new int[]{a, b};
            }
        }
    }
  • 相关阅读:
    Scrapy框架实现持久化存储
    Scrapy框架的介绍和基本使用
    处理页面动态加载数据
    爬虫数据解析
    Python爬虫基础
    Flask详解(下篇)
    Flask详解(中篇)
    CentOS 中的性能监测命令vmstat
    CentOS 7安装MySQL 8.0.15
    CF B.Kind Anton(4月8号)
  • 原文地址:https://www.cnblogs.com/fmgao-technology/p/13169139.html
Copyright © 2020-2023  润新知