zoukankan      html  css  js  c++  java
  • 简单算法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};
            }
        }
    }
  • 相关阅读:
    FZU 2112 并查集、欧拉通路
    HDU 5686 斐波那契数列、Java求大数
    Codeforces 675C Money Transfers 思维题
    HDU 5687 字典树插入查找删除
    HDU 1532 最大流模板题
    HDU 5384 字典树、AC自动机
    山科第三届校赛总结
    HDU 2222 AC自动机模板题
    HDU 3911 线段树区间合并、异或取反操作
    CodeForces 615B Longtail Hedgehog
  • 原文地址:https://www.cnblogs.com/fmgao-technology/p/13169139.html
Copyright © 2011-2022 走看看