1
Chingim 2020-01-29 21:16:24 +08:00
每个字符肯定都要处理一遍, 所以 O(n) 的时间复杂度少不了
|
2
fengtons 2020-01-29 21:16:25 +08:00 via Android
通过 ascii 码判断并加减完成转换?
|
3
rigortek 2020-01-29 21:20:53 +08:00 via iPhone
正则表达式
|
4
0TSH60F7J2rVkg8t 2020-01-29 21:23:23 +08:00 via iPhone
ascii 码,一遍循环,<x 的话+x,>x 的话-x,很容易。查下 ascii table 就知道 x 是几了
|
6
Mithril 2020-01-29 21:25:08 +08:00
如果是兼容 ASCII 编码的字符串直接位运算就可以。
|
7
KentY 2020-01-29 21:27:00 +08:00
我会用 ascii code 的方法. 有兴趣可以看看 vim 实现的"~"
|
9
ysc3839 2020-01-29 21:36:45 +08:00
应该没有了,用普通的方法,编译器会优化好的。
https://www.programmingsimplified.com/c/program/c-program-change-case 不过刚刚在 https://godbolt.org/ 试了一下,用 ctype.h 的 isupper islower toupper tolower,编译出来并没有内联,而是 call 这几个函数。觉得 call 影响性能的话还是直接写判断和加减比较好。 |
10
tonytonychopper 2020-01-29 21:42:36 +08:00
用啥方法都是 O(n),而且像楼上说到,编译器会优化。
|
11
52coder 2020-01-29 22:22:36 +08:00
@ysc3839 赞同,使用 c 库里的 isupper 等函数没内联暂开的话,可以手写函数 inline,毕竟就判断个 ascii 码范围,应该可以实现内联。
|
12
JerryCha 2020-01-29 22:24:44 +08:00
那么有没有什么办法能保证每个字符都遍历到且时间复杂度小于 O(n)呢(比如说 O(logn))
|
13
Mithril 2020-01-29 22:25:34 +08:00 27
大写字符是 65~90,小写是 97~112
二进制是 0100 0001~0101 1010 和 0110 0001~0111 1010 比如 01010001A,变成 01100001a 你可以直接翻转第六位,就是异或个 0010 0000 这个 0010 0000 在 ASCII 里面代表空格,所以你直接异或一个空格就可以。当然你得首先判断它是字符。 ASCII 当初就是这么设计的,大小写基本都是对称的位置。 另外虽然 ASCII 用来编码字符,但是对应数字那部分都是 0011 开头的。你把这部分 mask 掉剩下的就是字符所表示的实际数值。 兼容的 UTF8 也是一样的。不过正常来说,你要做一个完美的大小写转换,需要先判断 culture 才行。不过简单的可以就这么直接做了。 |
14
thedrwu 2020-01-29 23:08:04 +08:00 via Android
希腊字母?
带 accent/umlaut 的字母? 不知道 tr 能不能做。至少 vim 里的~可以完美转换。 |
15
wangyzj 2020-01-29 23:10:42 +08:00
ascii 吧
|
16
Believer 2020-01-29 23:13:40 +08:00
ascii table
|
17
Bromine0x23 2020-01-29 23:16:30 +08:00
@JerryCha 每个字符都遍历到 ≡ 时间复杂度至少是 O(n)
|
18
zhx1991 2020-01-29 23:27:53 +08:00
?
需要遍历就是 O(n) 的 |
20
imn1 2020-01-29 23:45:07 +08:00
位运算
if (ch & 32) ch = ch & 223 else ch = ch | 225 |
21
demos 2020-01-29 23:51:19 +08:00
|
22
crab 2020-01-30 01:05:54 +08:00
判断范围然后异或 0x20
|
23
ericgui 2020-01-30 06:00:15 +08:00 via Android
hashmap ?提前搞好对应关系?
|
24
augustheart 2020-01-30 10:27:53 +08:00
最快的方法就只有遍历字符判断这一种。如果要进一步优化,用查表应该比 if 快一丁点,但是不会有多显著
|
25
icyalala 2020-01-30 10:37:32 +08:00 2
即使都是 O(n), 效率也会相差甚远。
尤其是带分支的来判断范围的,在输入是混合符号的情况下,分支预测失败会导致效率会降低好几倍。 查表+unrolling 是我能想到最快的。 |
26
Windsooon 2020-01-30 10:55:40 +08:00
1. 如果可以使用额外空间的话,先建立大小写字母的对应哈希表,然后遍历替换。空间复杂度是常量,时间复杂度是 O(n),n 为字符串长度。
2. 如果不能使用额外空间的话,可以先实现两个辅助函数,一个将大写字母转成小写字母,一个将小写字母转成大写字母。然后遍历字符串,先判断是大写还是小写,然后调用对应的函数。 不可能存在低于 O(n) 时间复杂度( n 为字符串长度)的方法。 1. 假设存在这样的算法,不需要遍历所有字符串即可完成替换。 2. 设立目标字符串 A,选定其中一个字符 a 为此算法无需遍历的。将 a 的大小写翻转,得到新字符串 A' 3. 因为算法没有遍历 a,所以算法对 A 与 A'得到的结果应该是一样的,不符合实际情况。 4. 所以不存在这样的算法。 |
29
2exploring 2020-01-30 12:43:25 +08:00 1
自定义 ascii table,把其中大写和小写字母位置换一下,其余的和标准 ascii table 一样。转的时候直接用字符当下标访问自定义的 ascii table 就是转换后的值。
这样不用比较,没有分支,也许会比较快,具体怎么样你要跑跑才知道。 这个方法稍微改一下还可以用于 utf-8 编码的文本。这次自定义的表不是存 ascii 字符了,而是在大小写字母的位置放 0x20,其他位置放 0,操件由直接赋值改为异或后赋值(在许多机器上 a ^= b 和 a = b 的执行效率是一样的),原理上面有提到了。 |
30
2exploring 2020-01-30 12:44:45 +08:00
@Windsooon 你确定一次比较就能知道是大小写?
|
31
2exploring 2020-01-30 12:56:06 +08:00
@inhzus 你看我上面说的法子够快吗?不要把 hash 想复杂了,其实就是一个函数映射关系,这个问题里输入值是有限的,且连续的,且数量不大的,这种情况提前打个表,还要多简单。
|
32
flyoungstudio 2020-01-30 13:19:00 +08:00
Shell:
echo abcXYZhello123 | tr [a-z] [A-Z] |
33
alphatoad 2020-01-30 13:25:02 +08:00 via iPhone
遇事不决,fpga
|
34
luozic 2020-01-30 13:53:39 +08:00 via iPhone
全部是英文和数字,遍历一次需要 O(n)。有啥方法不用遍历再转换?
|
35
nvkou 2020-01-30 14:05:17 +08:00 via Android
抛砖引玉。像这种上下文无关的任务可以显卡并行化处理。不过脱离 php 范畴了。
|
37
ts8zs 2020-01-31 13:19:47 +08:00
直接加个网页字体...
|