目录

  • 位图和比较器的简单应用
    • 一、位图
      • 1.位图的功能
      • 2.位图的好处
      • 3.位图的实现
    • 二、用位运算实现加减乘除
      • 1.加法
      • 2.减法
      • 3.乘法
      • 4.除法
    • 三、位运算完成大小比较
    • 四、比较器
      • 1.应用在系统排序方法中
      • 2.应用在与排序有关的结构中优先级队列(堆)、有序表
    • 五、合并多个有序链表
    • 六、写在后面

位图和比较器的简单应用

一、位图

1.位图的功能

记录信息

例如,用一个 int 类型的变量的每个二进制位来记录 0−310-310−31 的出现情况。

2.位图的好处

可以用更小的空间来实现 map 的功能。

3.位图的实现

import java.util.HashSet;public class Code02_BitMap2 {// 位图的实现public static class BitMap {private long[] bits;public BitMap(int max) {bits = new long[(max + 64) >> 6];}public void add(int num) {// 注意要用 1Lbits[num >> 6] |= (1L << (num & 63));}public void delete(int num) {bits[num >> 6] &= ~(1L << (num & 63));}public boolean contains(int num) {return (bits[num >> 6] & (1L << (num & 63))) != 0;}}//对数器public static void main(String[] args) {System.out.println("测试开始!");int max = 10000;BitMap bitMap = new BitMap(max);HashSet<Integer> set = new HashSet<>();int testTime = 10000000;for (int i = 0; i < testTime; i++) {int num = (int) (Math.random() * (max + 1));double decide = Math.random();if (decide < 0.333) {bitMap.add(num);set.add(num);} else if (decide < 0.666) {bitMap.delete(num);set.remove(num);} else {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");break;}}}for (int num = 0; num <= max; num++) {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");}}System.out.println("测试结束!");}}

二、用位运算实现加减乘除

用位运算实现+ - * /

1.加法

// 测试链接:https://leetcode.cn/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/
public class BitAddMinusMultiDiv {public static int add(int a, int b) {int sum = a;while (b != 0) {sum = a ^ b;  // 不进位和b = (a & b) << 1;  // 进位和a = sum;}return sum;}}

2.减法

// 测试链接: 无
public class BitAddMinusMultiDiv {// a - b   =>   a + (-b) public static int minus(int a, int b) {return add(a, negNum(b));}// n  =>  -npublic static int negNum(int n) {return add(~n, 1);}public static int add(int a, int b) {int sum = a;while (b != 0) {sum = a ^ b;b = (a & b) << 1;a = sum;}return sum;}}

3.乘法

原理同十进制乘法

// 测试链接:https://leetcode.cn/problems/recursive-mulitply-lcci/
public class BitAddMinusMultiDiv {// 递归方法 支持负数public int multiply(int A, int B) {if (B == 0) return 0;if (B == 1) return A;return multiply(A, (B & 1)) + multiply(A << 1, B >>> 1);}// 非递归方法 支持负数// a * b   =>  a 逐位乘 b 的二进制 ,并且错位相加public static int multi(int a, int b) {int res = 0;while (b != 0) {if ((b & 1) != 0) {res = add(res, a); // 加错位后的结果}a <<= 1; // a 左移一位 即错位b >>>= 1; // b 无符号右移一位,即消除最右边用过的一位数}return res;}public static int add(int a, int b) {int sum = a;while (b != 0) {sum = a ^ b;b = (a & b) << 1;a = sum;}return sum;}}

4.除法

// 测试链接:https://leetcode.cn/problems/divide-two-integers/
public class BitAddMinusMultiDiv {public static int add(int a, int b) {int sum = a;while (b != 0) {sum = a ^ b;b = (a & b) << 1;a = sum;}return sum;}public static int negNum(int n) {return add(~n, 1);}public static int minus(int a, int b) {return add(a, negNum(b));}public static int multi(int a, int b) {int res = 0;while (b != 0) {if ((b & 1) != 0) {res = add(res, a);}a <<= 1;b >>>= 1;}return res;}public static boolean isNeg(int n) {return n < 0;}public static int div(int a, int b) {int x = isNeg(a) ? negNum(a) : a;int y = isNeg(b) ? negNum(b) : b;int res = 0;for (int i = 30; i >= 0; i = minus(i, 1)) {if ((x >> i) >= y) {res |= (1 << i);x = minus(x, y << i);}}return isNeg(a) ^ isNeg(b) ? negNum(res) : res;}public static int divide(int a, int b) {if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {return 1;} else if (b == Integer.MIN_VALUE) {return 0;} else if (a == Integer.MIN_VALUE) {if (b == negNum(1)) {return Integer.MAX_VALUE;} else {// a / b// (a + 1) / b == c// a - (b * c) = d// d / b = e// c + eint c = div(add(a, 1), b);return add(c, div(minus(a, multi(c, b)), b));}} else {return div(a, b);}}}

三、位运算完成大小比较

如何不用任何比较判断语句,就可以返回两个数中较大的那个

/*** @author 杨思远* @version 1.0* @title 位运算完成大小比较* @date 2022/7/16 0:52* @description 本方法原创 不一定为最优解    a < b => -1     a == b => -1     a > b => 1*/
public class BitComparisonOfSize {// 只使用 !=public static int compare(int a, int b) {if (a >>> 31 != b >>> 31) return b >>> 31 - a >>> 31;for (int i = 30; i > 0; i--) {if (a >>> i != b >>> i) return a >>> i - b >>> i;}return 0;}// 不使用任何比较判断语句 ( > < = != >= <= )public static int compare2(int a, int b) {return a - b >>> 31;}public static void main(String[] args) {System.out.println("测试开始");for (int i = 0; i < 1000000; i++) {int a = (int) (Math.random() * Integer.MIN_VALUE) * Math.random() < 0.5 ? 1 : -1;int b = (int) (Math.random() * Integer.MIN_VALUE) * Math.random() < 0.5 ? 1 : -1;int res = compare(a, b);int res2 = compare2(a, b);int acceptedAnswer = Integer.compare(a, b);if (res != acceptedAnswer || res2 != acceptedAnswer) {System.out.println("错误:a:" + a + ",b:" + b);}}System.out.println("测试结束");}}

四、比较器

1.应用在系统排序方法中

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;public class ShowComparator {public static class Student {public String name;public int id;public int age;public Student(String name, int id, int age) {this.name = name;this.id = id;this.age = age;}}// 谁id大,谁放前!public static class IdComparator implements Comparator<Student> {// 如果返回负数,认为第一个参数应该排在前面// 如果返回正数,认为第二个参数应该排在前面// 如果返回0,认为谁放前面无所谓@Overridepublic int compare(Student o1, Student o2) {if (o1.id < o2.id) {return 1;} else if (o2.id < o1.id) {return -1;} else {return 0;}}}// 谁age大,谁放前!public static class AgeComparator implements Comparator<Student> {// 如果返回负数,认为第一个参数应该排在前面// 如果返回正数,认为第二个参数应该排在前面// 如果返回0,认为谁放前面无所谓@Overridepublic int compare(Student o1, Student o2) {if (o1.age < o2.age) {return 1;} else if (o2.age < o1.age) {return -1;} else {return 0;}}}public static void printArray(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}public static void printStudents(Student[] students) {for (int i = 0; i < students.length; i++) {System.out.println(students[i].name + ", " + students[i].id + ", " + students[i].age);}}public static void main(String[] args) {int[] arr = { 8, 1, 4, 1, 6, 8, 4, 1, 5, 8, 2, 3, 0 };printArray(arr);Arrays.sort(arr);printArray(arr);Student s1 = new Student("张三", 5, 27);Student s2 = new Student("李四", 1, 17);Student s3 = new Student("王五", 4, 29);Student s4 = new Student("赵六", 3, 9);Student s5 = new Student("左七", 2, 34);Student[] students = { s1, s2, s3, s4, s5 };printStudents(students);System.out.println("=======");Arrays.sort(students, new IdComparator());printStudents(students);System.out.println("=======");ArrayList<Student> arrList = new ArrayList<>();arrList.add(s1);arrList.add(s2);arrList.add(s3);arrList.add(s4);arrList.add(s5);for (Student s : arrList) {System.out.println(s.name + ", " + s.id + ", " + s.age);}System.out.println("=======");arrList.sort(new AgeComparator());for (Student s : arrList) {System.out.println(s.name + ", " + s.id + ", " + s.age);}}}

2.应用在与排序有关的结构中优先级队列(堆)、有序表

import java.util.Comparator;
import java.util.PriorityQueue;public class ShowComparator2 {public static class MyComparator implements Comparator<Integer> {// 负,第一个参数在前// 正,第二个参数在前// 0, 谁放前都行@Overridepublic int compare(Integer o1, Integer o2) {if (o1 < o2) {return 1;} else if (o1 > o2) {return -1;} else {return 0;}}}public static class Student {public String name;public int id;public int age;public Student(String name, int id, int age) {this.name = name;this.id = id;this.age = age;}}// 谁id大,谁放前!public static class IdComparator implements Comparator<Student> {// 如果返回负数,认为第一个参数应该排在前面// 如果返回正数,认为第二个参数应该排在前面// 如果返回0,认为谁放前面无所谓@Overridepublic int compare(Student o1, Student o2) {if (o1.id < o2.id) {return 1;} else if (o2.id < o1.id) {return -1;} else {return 0;}}}public static void main(String[] args) {String str1 = "abc";String str2 = "b";System.out.println(str1.compareTo(str2));PriorityQueue<Student> heap = new PriorityQueue<>(new IdComparator());Student s1 = new Student("张三", 5, 27);Student s2 = new Student("李四", 1, 17);Student s3 = new Student("王五", 4, 29);Student s4 = new Student("赵六", 3, 9);Student s5 = new Student("左七", 2, 34);heap.add(s1);heap.add(s2);heap.add(s3);heap.add(s4);heap.add(s5);System.out.println("=========");while (!heap.isEmpty()) {Student s = heap.poll();System.out.println(s.name + ", " + s.id + ", " + s.age);}}}

五、合并多个有序链表

Leetcode原题 https://leetcode.com/problems/merge-k-sorted-lists

import java.util.Comparator;
import java.util.PriorityQueue;
// 时间复杂度 O(M*log(N))
// 测试链接:https://leetcode.cn/problems/merge-k-sorted-lists/
public class MergeKSortedLists {public static class ListNode {public int val;public ListNode next;}public static class ListNodeComparator implements Comparator<ListNode> {@Overridepublic int compare(ListNode o1, ListNode o2) {return o1.val - o2.val; }}public static ListNode mergeKLists(ListNode[] lists) {if (lists == null) {return null;}PriorityQueue<ListNode> heap = new PriorityQueue<>(new ListNodeComparator());for (int i = 0; i < lists.length; i++) {if (lists[i] != null) {heap.add(lists[i]);}}if (heap.isEmpty()) {return null;}ListNode head = heap.poll();ListNode pre = head;if (pre.next != null) {heap.add(pre.next);}while (!heap.isEmpty()) {ListNode cur = heap.poll();pre.next = cur;pre = cur;if (cur.next != null) {heap.add(cur.next);}}return head;}}

六、写在后面

欢迎关注,会经常记录一些算法学习中遇到的问题。

欢迎随时留言讨论,与君共勉,知无不答!

05.位图和比较器的简单应用相关推荐

  1. 比较器的简单介绍及应用

    概述 在许多情况下,需要知道两个信号中哪个比较大,或者一个信号何时超出预设的电压.用运算放大器便可以容易搭建一个简单的电路实现该功能.在同相比较电路中,当输入电压超过反相电压时,输出电压将从低电平转换 ...

  2. PS初识 位图 矢量图 的简单理解

    PS初识 位图.矢量图 的理解 PS是位图的处理软件 绝大数图片都是位图 位图放大缩小后会失真 位图的优点:位图色彩细腻 兼容性强 内存小 Ai是矢量图处理软件 矢量图:放大缩小后不会失真 使用方向: ...

  3. 用位运算完成大小比较

    目录 只用位运算完成大小比较 写在后面 只用位运算完成大小比较 如何不用任何比较判断语句,就可以返回两个数中较大的那个 /*** @author 杨思远* @version 1.0* @title 位 ...

  4. 专转本就业歧视怎么消除_人工智能可以帮助消除歧视

    专转本就业歧视怎么消除 Recently, a lot articles have been published covering cases in which Artificial Intellig ...

  5. 时间序列预测——深度好文,ARIMA是最难用的(数据预处理过程不适合工业应用),线性回归模型简单适用,预测趋势很不错,xgboost的话,不太适合趋势预测,如果数据平稳也可以使用。...

    补充:https://bmcbioinformatics.biomedcentral.com/articles/10.1186/1471-2105-15-276 如果用arima的话,还不如使用随机森 ...

  6. 【数据结构与算法】7.位图算法、12306抢票算法

    前言 本文收录于专辑:http://dwz.win/HjK,点击解锁更多数据结构与算法的知识. 你好,我是彤哥,一个每天爬二十六层楼还不忘读源码的硬核男人. 相信大家都有过抢票.刷票的经验,每年年底, ...

  7. java 实现中文排序,Java自定义比较器实现中文排序

    compareTo 方法 compareTo()是两个字符串对象比较大小,返回一个整数值,如果调用字符串对象大,返回正整数,反之,返回负整数.相等则返回0.compareTo()是两个字符串对象按AS ...

  8. UWP 手绘视频创作工具技术分享系列 - 位图的绘制

    UWP 手绘视频创作工具技术分享系列 - 位图的绘制 原文:UWP 手绘视频创作工具技术分享系列 - 位图的绘制 前面我们针对 SVG 的解析和绘制做了介绍,SVG 是图片的一种形式,而另一种很重要的 ...

  9. 如何减小电压跟随器输出电阻_补课贴 | 关于运算放大器和比较器的异同,那些你不得不知道的小知识!...

    在直入正题讲解运算放大器的异同之前,小A先来帮助大家简单回顾一下运算放大器和比较器的基础知识: 比较器是一种带有反相和同相两个输入端以及一个输出端的器件,该输出端的输出电压范围一般在供电的轨到轨之间. ...

最新文章

  1. 动画requestAnimationFrame
  2. GDALWarp设置GDALWarpOptions::dfWarpMemoryLimit过大时处理失败
  3. 绘制简单的正太分布图
  4. python 插入排序算法
  5. 给matlab图加图注,matlab学习5-数据可视化4-gai.ppt
  6. NAT原理?代理服务器原理?
  7. 4thweek.P_problemB .poj1505copy books.二分法
  8. python能开发android吗_python可以开发安卓吗
  9. Python编写区块链
  10. JAVA 微信支付 native方式
  11. 使用 Responsive Elements 快速构建响应式网站
  12. [转载] 百科全说——漆浩:观手分辨五行人教您五行人的养生绝招(11-01-1011-01-11)...
  13. 如何使用postman带Token测试接口?
  14. PRINCE2认证好在哪?
  15. 前端工程师的第一个Flutter应用
  16. PJzhang:我发现一个有两个答案的数独题
  17. 十几减9的口算题_一年级数学《口算十几减9》教案
  18. 【jQWidgets】jqxGrid控件在页面上重新加载的问题
  19. wgs84坐标格式转换度分秒_ArcGIS坐标单位转换(米和度分秒之间是如何转换的?)...
  20. 微信开发系列之自定义菜单实现

热门文章

  1. hibernate 根据方言生成sql
  2. 对不起navicat我投入了DataGrip的怀抱
  3. Android中实现图片平移、缩放、旋转同步进行
  4. J2EE大作业遇到的问题及解决方案:
  5. HDU2159.FATE-完全背包
  6. unity3d 禁用脚本
  7. Java基于opencv—矫正图像
  8. 常见的手机验证api接口有哪些
  9. 外汇天眼:外汇储备减少对新兴市场货币构成风险
  10. OrCAD Capture CIS 怎样修改Title_Block