/** * 超时 * * @param time * @return */ public int numPairsDivisibleBy60(int[] time) { int result = 0; for (int i = 0; i < time.length - 1; i++) { for (int j = i + 1; j < time.length; j++) { int value = (time[i] + time[j]) % 60; if (value == 0) result++; } } return result; }
public int numPairsDivisibleBy601(int[] time) { // 每个元素取60余 time = Arrays.stream(time).map(x -> x % 60).toArray(); int[] arrCount = new int[60]; // 统计对应下标数 Arrays.stream(time).forEach(x -> { arrCount[x]++; }); // 余数是 0 或 30 的两两配对 int result = qiuhe(arrCount[0]) + qiuhe(arrCount[30]); // 其余互相配对 for (int i = 1; i < 30; i++) { int count1 = arrCount[i]; int count2 = arrCount[60 - i]; result += count1 * count2; } return result; }
/** * 求两两配对数 * * @param num * @return */ private int qiuhe(int num) { if (num < 2) return 0; // (num-1)! return num * (num - 1) / 2; }
很好理解,不过速度还是慢,通过阅读其它人的代码后发现了另一种 O(n) 解法,cool~
1 2 3 4 5 6 7 8 9 10 11 12 13
public int numPairsDivisibleBy602(int[] time) { int result = 0; int[] arrCount = new int[60]; for (int t : time) { // 对应的下标 int index = t == 0 ? 0 : 60 - t % 60; // 与已经统计的数进行匹配 可防止两两重复匹配 result += arrCount[index]; // 对应数字加一 arrCount[t % 60]++; } return result; }
public ListNode reverseBetween(ListNode head, int m, int n) { if (head == null) return null; // 新建一个节点并指向 head ListNode dummy = new ListNode(0); dummy.next = head; ListNode pre = dummy; // pre 为需要反转的前节点 for (int i = 0; i < m - 1; i++) pre = pre.next;
mysql> explain select id, sum(moneys) from sales2 group by id\G; **************************** 1. row ************************************* id: 1 select_type: SIMPLE table: sales2 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: Using temporary; Using filesort 1 row in set(0.00 sec)
mysql> explain select id, sum(moneys) from sales2 group by id order by null\G; **************************** 1. row ************************************* id: 1 select_type: SIMPLE table: sales2 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: Using temporary
从上面的例子可以看出第一个 SQL 语句需要进行“filesort”,而第二个 SQL 由于 ORDER BY NULL 不需要进行“filesort”,而 filesort 往往非常耗费时间。
优化 ORDER BY 语句
在某些情况中,MySQL 可以使用一个索引来满足 ORDER BY 子句,而不需要额外的排序。WHERE 条件和 ORDER BY 使用相同的索引,并且 ORDER BY 的顺序和索引顺序相同,并且 ORDER BY 的字段都是升序或者都是降序。
例如,下列 SQL 可以使用索引:
1 2 3
SELECT * FROM t1 ORDER BY key_part1,key_part2,...; SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;
但是在以下几种情况下则不使用索引:
1 2 3
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC; --order by 的字段混合 ASC 和 DESC SELECT * FROM t1 WHERE key2=constant ORDER BY key1; --用于查询行的关键字与 ORDER BY 中所使用的不相同 SELECT * FROM t1 ORDER BY key1, key2; --对不同的关键字使用 ORDER BY
优化嵌套查询
MySQL 4.1 开始支持 SQL 的子查询。这个技术可以使用 SELECT 语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。使用子查询可以一次性地完成很多逻辑上需要多个步骤才能完成的 SQL 操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询可以被更有效率的连接(JOIN)替代。