private <T> ObjectConstructor<T> newUnsafeAllocator( final Type type, final Class<? super T> rawType) { return new ObjectConstructor<T>() { private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create(); @SuppressWarnings("unchecked") @Override public T construct() { try { Object newInstance = unsafeAllocator.newInstance(rawType); return (T) newInstance; } catch (Exception e) { throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". " + "Registering an InstanceCreator with Gson for this type may fix this problem."), e); } } }; }
@kotlin.internal.InlineOnly public inline fun <R> run(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }
with
with语法糖不再是⼀个拓展函数了,⽽是需要在语法糖的第⼀个参数⾥⾯传⼊接收者对象的实例,第⼆个参数就是带接收者的函数 字⾯值实例,返回的也是 block 调⽤的结果,这⼀点和 run 语法糖类似。
调用示例:
1 2 3 4
val test: String ?= "" with(test) { print("with") }
实现源码:
1 2 3 4 5 6 7
@kotlin.internal.InlineOnly public inline fun <T, R> with(receiver: T, block: T.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return receiver.block() }
apply
apply 函数内部会自带调用者,返回的是调用者本身。 调用示例:
1 2 3 4
val test: String ?= "" test?.apply { substring(1) }
实现源码:
1 2 3 4 5 6 7 8
@kotlin.internal.InlineOnly public inline fun <T> T.apply(block: T.() -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() return this }
alos
alos 和 let 类似,区别在于 alos 的返回值是 caller 本身,而 let 返回的是 block 的执行结果。 调用示例:
1 2 3 4
val test: String ?= "" test?.also { it.length }
实现源码:
1 2 3 4 5 6 7 8 9
@kotlin.internal.InlineOnly @SinceKotlin("1.1") public inline fun <T> T.also(block: (T) -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block(this) return this }
let
let 方法块中,可以通过 it 来调用 caller, 返回值是方法块的执行结果。
调用示例:
1 2 3 4
val test: String ?= "" test?.let { it.length }
源码:
1 2 3 4 5 6 7
@kotlin.internal.InlineOnly public inline fun <T, R> T.let(block: (T) -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }
It is a Unicode space character ({@code SPACE_SEPARATOR},
{@code LINE_SEPARATOR}, or {@code PARAGRAPH_SEPARATOR})
but is not also a non-breaking space ({@code '\u005Cu00A0'},
{@code '\u005Cu2007'}, {@code '\u005Cu202F'}).
It is {@code '\u005Ct'}, U+0009 HORIZONTAL TABULATION.
It is {@code '\u005Cn'}, U+000A LINE FEED.
It is {@code '\u005Cu000B'}, U+000B VERTICAL TABULATION.
It is {@code '\u005Cf'}, U+000C FORM FEED.
It is {@code '\u005Cr'}, U+000D CARRIAGE RETURN.
It is {@code '\u005Cu001C'}, U+001C FILE SEPARATOR.
It is {@code '\u005Cu001D'}, U+001D GROUP SEPARATOR.
It is {@code '\u005Cu001E'}, U+001E RECORD SEPARATOR.
It is {@code '\u005Cu001F'}, U+001F UNIT SEPARATOR.
publicclassSolution{ publicintlengthOfLongestSubstring(String s){ int n = s.length(); int ans = 0; for (int i = 0; i < n; i++) for (int j = i + 1; j <= n; j++) if (allUnique(s, i, j)) ans = Math.max(ans, j - i); return ans; }
publicbooleanallUnique(String s, int start, int end){ Set<Character> set = new HashSet<>(); for (int i = start; i < end; i++) { Character ch = s.charAt(i); if (set.contains(ch)) returnfalse; set.add(ch); } returntrue; } }
publicclassSolution{ publicintlengthOfLongestSubstring(String s){ int n = s.length(); Set<Character> set = new HashSet<>(); int ans = 0, i = 0, j = 0; while (i < n && j < n) { // try to extend the range [i, j] if (!set.contains(s.charAt(j))){ set.add(s.charAt(j++)); ans = Math.max(ans, j - i); } else { set.remove(s.charAt(i++)); } } return ans; } }
复杂度分析
时间复杂度:O(2n)=O(n)O(2n) = O(n)O(2n)=O(n),在最糟糕的情况下,每个字符将被 iii 和 jjj 访问两次。
上述的方法最多需要执行 2n 个步骤。事实上,它可以被进一步优化为仅需要 n 个步骤。我们可以定义字符到索引的映射,而不是使用集合来判断一个字符是否存在。 当我们找到重复的字符时,我们可以立即跳过该窗口。
也就是说,如果 s[j]s[j]s[j] 在 [i,j)[i, j)[i,j) 范围内有与 j′j'j′ 重复的字符,我们不需要逐渐增加 iii 。 我们可以直接跳过 [i,j′][i,j'][i,j′] 范围内的所有元素,并将 iii 变为 j′+1j' + 1j′+1。
Java(使用 HashMap)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicclassSolution{ publicintlengthOfLongestSubstring(String s){ int n = s.length(), ans = 0; Map<Character, Integer> map = new HashMap<>(); // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { if (map.containsKey(s.charAt(j))) { i = Math.max(map.get(s.charAt(j)), i); } ans = Math.max(ans, j - i + 1); map.put(s.charAt(j), j + 1); } return ans; } }
publicclassSolution{ publicintlengthOfLongestSubstring(String s){ int n = s.length(), ans = 0; int[] index = newint[128]; // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { i = Math.max(index[s.charAt(j)], i); ans = Math.max(ans, j - i + 1); index[s.charAt(j)] = j + 1; } return ans; } }
classSolution{ publicint[] intersection(int[] nums1, int[] nums2) { if (nums1 == null || nums1.length ==0 || nums2 == null || nums2.length == 0){ returnnewint[0]; } Set<Integer> set = new HashSet<>(); Set<Integer> res = new HashSet<>(); for (int i = 0; i < nums1.length; i++) { set.add(nums1[i]); } for (int i = 0; i < nums2.length; i++) { if (set.contains(nums2[i])){ res.add(nums2[i]); } } int num[] = newint[res.size()]; int i = 0; for (Iterator it = res.iterator(); it.hasNext();){ num[i++] = (int) it.next(); } return num; } }