classTrie{ int N = 100009; // 直接设置为十万级 int[][] trie; int[] count; int index;
publicTrie(){ trie = newint[N][26]; count = newint[N]; index = 0; } publicvoidinsert(String s){ int p = 0; for (int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (trie[p][u] == 0) trie[p][u] = ++index; p = trie[p][u]; } count[p]++; } publicbooleansearch(String s){ int p = 0; for (int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (trie[p][u] == 0) returnfalse; p = trie[p][u]; } return count[p] != 0; } publicbooleanstartsWith(String s){ int p = 0; for (int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (trie[p][u] == 0) returnfalse; p = trie[p][u]; } returntrue; } }
classTrie{ classTrieNode{ boolean end; TrieNode[] tns = new TrieNode[26]; }
TrieNode root; publicTrie(){ root = new TrieNode(); }
publicvoidinsert(String s){ TrieNode p = root; for(int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (p.tns[u] == null) p.tns[u] = new TrieNode(); p = p.tns[u]; } p.end = true; }
publicbooleansearch(String s){ TrieNode p = root; for(int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (p.tns[u] == null) returnfalse; p = p.tns[u]; } return p.end; }
publicbooleanstartsWith(String s){ TrieNode p = root; for(int i = 0; i < s.length(); i++) { int u = s.charAt(i) - 'a'; if (p.tns[u] == null) returnfalse; p = p.tns[u]; } returntrue; } }
classSolution{ publicintminMoves(int[] nums){ //每次使n-1个元素增加1 相当于每次将一个元素减小1,直到所有元素都等于刚开始nums最小的那个元素。 //这个次数就是所求的次数,即最终的答案应该是(num- min)求和,即每个num中每个元素与最小值的差求和 //变形得sum(nums) - min*n int n = nums.length; int sum = 0,min = nums[0]; for(int num :nums) { min = Math.min(min,num); sum +=num; } return (int)sum - n * min;
但是看到题解发现有很多高大上的写法,如 模拟(遍历)
先对 num 进行「从高到低」的检查,找到最高位 1 的位置 s,然后再对$num $进行遍历,将低位到 s 位的位置执行逐位取反操作。
这里使用了位运算,Java中的为运算有三种
<<:左移,num<<1相当于num∗2。
>>:右移,num>>1相当于num/2。
>>>:无符号右移,忽略符号位,空位都以0补齐
classSolution{ publicintfindComplement(int num){ int s = -1; //从int的最高位开始 不断右移,找到最高位1所在的位置s for (int i = 31; i >= 0; i--) { if (((num >> i) & 1) != 0) { s = i; break; } } int ans = 0; //然后从最低位开始,如果某位为1则乘2的i次方(1<<i) for (int i = 0; i < s; i++) { if (((num >> i) & 1) == 0) ans |= (1 << i); } return ans; } }
模拟(lowbit)
如果num的二进制表示中最高位 1 的位置为 s 的话,那么实际上我们只需要对 num 的前 s−1 位进行取反即是答案(第 s 位的取反结果始终为 0)。
因此我们可以先使用 lowbit 操作来得到 num 二进制表示中最高位 1 的位置为 1,其余位为 0 时所代表的数字 x。
然后 x−1 即是二进制表示中前 s−1 位均为 1,其余位为 0 的数字,将其与 num 的取反数执行「按位与」操作,即可达到「仅对 num 的前 s−1 位进行取反」的效果。
classSolution{ publicintfindComplement(int num){ int x = 0; //求x 其中i & -i 为二进制与 for (int i = num; i != 0; i -= i & -i) x = i; return ~num & (x - 1); } }