leetcode-cn辅助

leetcode-cn刷题辅助脚本

  1. // ==UserScript==
  2. // @name leetcode-cn辅助
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.5
  5. // @description leetcode-cn刷题辅助脚本
  6. // @author You
  7. // @match https://leetcode-cn.com/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // ==/UserScript==
  11.  
  12. let featured = new Set([838,1469,1469,1681,1681,1538,1538,1906,1906,1669,1669,1582,1582,1581,1581,1448,1448,1542,1542,1638,1638,1590,1590,1679,1679,1484,1484,1651,1651,1630,1630,1592,1592,1384,1384,1485,1485,1682,1682,1533,1533,1676,1676,999,999,1540,1540,1628,1628,1571,1571,1579,1579,1536,1536,821,821,485,485,1541,1541,1444,1444,1586,1586,1665,1665,1645,1645,1606,1606,1519,1519,1620,1620,1653,1653,1591,1591,1622,1622,1531,1531,1636,1636,1602,1602,1650,1650,111,111,1222,1222,1555,1555,730,730,1362,1362,1522,1522,1505,1505,1641,1641,1908,1908,1625,1625,1660,1660,1196,1196,1662,1662,1011,1011,1475,1475,1907,1907,1903,1903,1300,1300,1486,1486,1539,1539,1546,1546,1356,1356,1178,1178,1044,1044,1290,1290,1457,1457,1495,1495,1605,1605,1397,1397,1454,1454,1904,1904,978,978,1673,1673,1532,1532,1610,1610,1142,1142,1593,1593,1570,1570,1634,1634,1623,1623,1248,1248,1916,1916,1911,1911,1637,1637,1471,1471,1463,1463,93,93,1144,1144,1240,1240,1247,1247,1199,1199,1621,1621,1477,1477,1644,1644,1564,1564,1476,1476,84,84,1598,1598,1629,1629,1924,1924,1910,1910,1609,1609,1172,1172,1036,1036,1668,1668,1014,1014,1578,1578,1550,1550,1337,1337,1282,1282,102,102,1028,1028,91,91,1378,1378,933,933,1909,1909,1545,1545,1667,1667,1152,1152,1666,1666,1180,1180,1678,1678,1923,1923,1268,1268,101,101,1613,1613,812,812,108,108,1446,1446,1253,1253,1234,1234,1298,1298,1420,1420,1511,1511,1604,1604,1547,1547,1424,1424,1534,1534,1159,1159,1474,1474,701,701,1245,1245,1462,1462,1135,1135,1368,1368,313,313,1518,1518,916,916,133,133,1306,1306,1639,1639,1567,1567,1059,1059,1350,1350,182,182,1588,1588,1921,1921,776,776,395,395,1174,1174,781,781,1648,1648,1284,1284,831,831,1611,1611,799,799,1595,1595,1914,1914,1315,1315,1575,1575,1635,1635,885,885,1191,1191,1241,1241,949,949,1557,1557,846,846,326,326,1913,1913,953,953,96,96,95,95,864,864,1607,1607,1308,1308,473,473,693,693,1912,1912,1263,1263,110,110,713,713,892,892,1120,1120,1322,1322,79,79,1464,1464,341,341,1252,1252,1537,1537,995,995,1012,1012,132,132,1347,1347,849,849,617,617,637,637,1286,1286,1019,1019,1554,1554,939,939,475,475,137,137,439,439,1672,1672,1824,1824,757,757,1603,1603,721,721,121,121,959,959,452,452,441,441,425,425,359,359,697,697,1915,1915,573,573,809,809,166,166,1353,1353,99,99,472,472,311,311,72,72,1790,1790,1568,1568,1766,1766,1052,1052,1093,1093,1287,1287,528,528,187,187,1183,1183,162,162,902,902,1323,1323,1319,1319,481,481,1239,1239,1553,1553,1150,1150,245,245,1655,1655,1920,1920,1095,1095,1373,1373,1405,1405,642,642,1740,1740,1302,1302,331,331,815,815,1365,1365,1377,1377,1004,1004,703,703,1880,1880,493,493,144,144,1425,1425,769,769,1888,1888,1366,1366,1922,1922,1359,1359,1341,1341,413,413,1255,1255,737,737,828,828,496,496,1260,1260,1018,1018,1033,1033,773,773,135,135,1407,1407,1429,1429,555,555,1140,1140,1048,1048,105,105,852,852,1181,1181,1069,1069,71,71,714,714,129,129,1431,1431,300,300]);
  13. let too_easy = new Set();
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. read_config();
  19.  
  20. // 注册(不可用)监听
  21. when(detectTable, () => {
  22. let tableObserver = new MutationObserver(process_problem_list);
  23. let options = {childList: true};
  24. let table = get_problem_list_dom();
  25. let tbody = table.getElementsByTagName('tbody')[0];
  26. tableObserver.observe(tbody, options);
  27. });
  28. when(detectTable, process_problem_list);
  29. })();
  30.  
  31. function save_config() {
  32. GM_setValue('easy_list', too_easy);
  33. }
  34.  
  35. function read_config() {
  36. too_easy = GM_getValue('easy_list');
  37. too_easy = new Set(too_easy);
  38. if (too_easy === undefined) {
  39. too_easy = new Set();
  40. }
  41. }
  42.  
  43. // 用于判断表格是否被加载
  44. function detectTable() {
  45. let table = get_problem_list_dom();
  46. if (table === undefined) {
  47. return false;
  48. }
  49. let tr = table.getElementsByTagName('tr')[0];
  50. if (tr === undefined) {
  51. return false;
  52. }
  53. return true;
  54. }
  55.  
  56. function get_problem_list_dom() {
  57. return document.getElementsByClassName('table-striped')[0];
  58. }
  59.  
  60. // 处理问题列表
  61. function process_problem_list() {
  62. console.log('called');
  63. let table = get_problem_list_dom();
  64. let trs = table.getElementsByTagName('tr');
  65.  
  66. for (let i = 1 ; i < trs.length-1 ; i++) {
  67. let row = get_row_data(trs[i]);
  68. console.log(row);
  69. // 删除操作
  70. if (should_delete_problem(row)) {
  71. delete_row(trs[i]);
  72. continue;
  73. }
  74.  
  75. // 修改操作
  76. modify_row(trs[i], row);
  77.  
  78. }
  79. }
  80.  
  81. function should_delete_problem(row) {
  82. if (row.difficulty == '简单') return true;
  83. if (row.status == 'locked') return true;
  84. return false;
  85. }
  86.  
  87. function get_row_data(tr) {
  88. let tds = tr.getElementsByTagName('td');
  89. let row = {};
  90.  
  91. /*
  92. 第一个字段,题目状态
  93. locked: 锁定题目
  94. solved: 已完成
  95. failed: 已尝试,未通过
  96. empty: 未尝试
  97. */
  98. let div = tds[0].firstElementChild;
  99. if (div.firstElementChild == null) {
  100. row.status = 'empty';
  101. } else {
  102. let span = div.firstElementChild;
  103. if (span.classList.contains('lock__13du')) {
  104. row.status = 'locked';
  105. } else if (span.classList.contains('text-success')) {
  106. row.status = 'solved';
  107. } else if (span.classList.contains('text-info')) {
  108. row.status = 'failed';
  109. } else {
  110. row.status = 'empty';
  111. }
  112. }
  113.  
  114. /*
  115. 第二个字段,id
  116. */
  117. let problem_id = Number(tds[1].innerText);
  118. row.problem_id = problem_id;
  119.  
  120. /*
  121. 第三个字段,题目名
  122. */
  123. let title = tds[2].getElementsByTagName('a')[0].innerText;
  124. row.title = title;
  125.  
  126. /*
  127. 第四个字段,题解数量
  128. */
  129. let num_of_solution = Number(tds[3].firstElementChild.innerText);
  130. row.solution_num = num_of_solution;
  131.  
  132. /*
  133. 第五个字段,通过率
  134. */
  135. let pass_rate = tds[4].innerText;
  136. row.pass_rate = pass_rate;
  137.  
  138. /*
  139. 第六个字段,难度
  140. */
  141. let difficulty = tds[5].firstElementChild.innerText;
  142. row.difficulty = difficulty;
  143.  
  144. return row;
  145. }
  146.  
  147. function modify_row(tr, row) {
  148. // 修改一行的显示
  149. // 1. 标记常考的题
  150. if (featured.has(row.problem_id)) {
  151. tr.style.backgroundColor = '#5ABE6F';
  152. }
  153.  
  154. // 2. 修改链接,能够在新窗口打开
  155. let link_td = tr.children[2];
  156. // 移除原来的链接,添加新的链接
  157. let href = link_td.firstChild.firstChild.firstChild.href;
  158. let a = document.createElement('a');
  159. a.innerText = link_td.innerText;
  160. a.href = href;
  161. link_td.removeChild(link_td.firstChild);
  162. link_td.appendChild(a);
  163.  
  164. // 3. 添加本地标记功能 TODO
  165. console.log(too_easy);
  166. if (too_easy.has(row.problem_id)) {
  167. add_easy_mark(tr.children[0]);
  168. }
  169. tr.children[0].addEventListener('click', () => {
  170. if (too_easy.has(row.problem_id)) {
  171. too_easy.delete(row.problem_id);
  172. remove_easy_mark(tr.children[0]);
  173. } else {
  174. too_easy.add(row.problem_id);
  175. add_easy_mark(tr.children[0]);
  176. }
  177. save_config();
  178. //add_easy_mark(tr.children[0]);
  179. });
  180. }
  181.  
  182. function contains_easy_mark(td) {
  183. let div = td.firstElementChild;
  184. let spans = div.getElementsByClassName('fa-check-circle-o');
  185. return spans.length != 0;
  186. }
  187. function add_easy_mark(td) {
  188. let div = td.firstElementChild;
  189. let spans = div.getElementsByClassName('fa-check-circle-o');
  190. if (spans.length == 0) {
  191. let span = document.createElement('span');
  192. span.classList.add('fa');
  193. span.classList.add('fa-check-circle-o');
  194. div.appendChild(span);
  195. }
  196. }
  197.  
  198. function remove_easy_mark(td) {
  199. let div = td.firstElementChild;
  200. let spans = div.getElementsByClassName('fa-check-circle-o');
  201. for (let i = 0 ; i < spans.length ; i++) {
  202. spans[i].remove();
  203. }
  204. }
  205.  
  206. function delete_row(tr) {
  207. //tr.remove();
  208. tr.setAttribute('hidden', true);
  209. }
  210.  
  211. function when(condition,func) {
  212. if (condition()) {
  213. func();
  214. } else {
  215. window.setTimeout(() => {when(condition, func)},1000);
  216. }
  217. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址