privatestaticbooleanisExisted(String id, String name) { Stringsql="select count(1) as num from " + static_TABLE + " where ID = '" + id + "' and NAME = '" + name + "'"; Stringnum= JdbcUtil.executeSelect(sql, "num"); return Integer.valueOf(num) > 0;
}
@Transactional( rollbackFor = {Exception.class}
) publicboolean saveOrUpdate(T entity) { if (null == entity) { returnfalse;
} else {
Class cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", newObject[0]); StringkeyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", newObject[0]); ObjectidVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty()); return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
}
}
😐分析上面的代码,首先作者使用了Lombok提供的@RequiredArgsConstructor注解,它的作用是为下面被 final 修饰的变量生成构造方法,即利用构造方法将AbstractCaptcha对象注入到Spring容器中,但是通过这种方式注入,默认情况下Bean是单例的,即多次请求会复用同一个Bean 。
EOF echo-e"\033[0m" echo-e"\033[1;34mToday is \033[1;32m$(date +%A,\ %B\ %d,\ %Y)\033[0m" echo-e"\033[1;34mThe time is \033[1;32m$(date +%r)\033[0m" echo-e"\033[1;34mYou are logged in to \033[1;32m$(hostname)\033[0m"
当以 root 为起点的长度为 k 的一段翻转完成后,再将下一个起始节点传入,直到整条链表都被处理完成。
当然,在 reverse 函数真正执行翻转前,需要先确保节点 root 后面至少有 k 个节点。
我们可以结合图解再来体会一下这个过程:
假设当前样例为 1->2->3->4->5->6->7 和 k = 3 :
然后我们调用 reverse(cur, k),在 reverse() 方法内部,几个指针的指向如图所示,会通过先判断 cur 是否为空,从而确定是否有足够的节点进行翻转:
然后先通过 while 循环,将中间的数量为 k - 1 的 next 指针进行翻转:
最后再处理一下局部的头结点和尾结点,这样一次 reverse(cur, k) 执行就结束了:
回到主方法,将 cur 往前移动 k 步,再调用 reverse(cur, k) 实现 k 个一组翻转:
Java 代码:
classSolution { public ListNode reverseKGr0up(ListNode head, int k) { ListNodedummy=newListNode(-1);
dummy.next = head; ListNodecur= dummy; while (cur != null) {
reverse(cur, k); intu= k; while (u-- > 0 && cur != null) cur = cur.next;
} return dummy.next;
} // reverse 的作用是将 root 后面的 k 个节点进行翻转 voidreverse(ListNode root, int k) { // 检查 root 后面是否有 k 个节点 intu= k; ListNodecur= root; while (u-- > 0 && cur != null) cur = cur.next; if (cur == null) return; // 进行翻转 ListNodetail= cur.next; ListNodea= root.next, b = a.next; // 当需要翻转 k 个节点时,中间有 k - 1 个 next 指针需要翻转 while (k-- > 1) { ListNodec= b.next;
b.next = a;
a = b;
b = c;
}
root.next.next = tail;
root.next = a;
}
}
C++ 代码:
classSolution { public: ListNode* reverseKGr0up(ListNode* head, int k){
ListNode* dummy = newListNode(-1);
dummy->next = head;
ListNode* cur = dummy; while (cur != NULL) { reverse(cur, k); int u = k; while (u-- > 0 && cur != NULL) cur = cur->next;
} return dummy->next;
} // reverse 的作用是将 root 后面的 k 个节点进行翻转 voidreverse(ListNode* root, int k){ // 检查 root 后面是否有 k 个节点 int u = k;
ListNode* cur = root; while (u-- > 0 && cur != NULL) cur = cur->next; if (cur == NULL) return; // 进行翻转
ListNode* tail = cur->next;
ListNode* a = root->next, *b = a->next; // 当需要翻转 k 个节点时,中间有 k - 1 个 next 指针需要翻转 while (k-- > 1) {
ListNode* c = b->next;
b->next = a;
a = b;
b = c;
}
root->next->next = tail;
root->next = a;
}
};
Python 代码:
classSolution: defreverseKGr0up(self, head: Optional[ListNode], k: int) -> Optional[ListNode]: # reverse 的作用是将 root 后面的 k 个节点进行翻转 defreverse(root, k): # 检查 root 后面是否有 k 个节点
u, cur = k, root while u > 0and cur:
cur = cur.next
u -= 1 ifnot cur: return # 进行翻转
tail = cur.next
a, b = root.next, root.next.next # 当需要翻转 k 个节点时,中间有 k - 1 个 next 指针需要翻转 while k > 1:
c, b.next = b.next, a
a, b = b, c
k -= 1
root.next.next = tail
root.next = a
dummy = ListNode(-1)
dummy.next = head
cur = dummy while cur:
reverse(cur, k)
u = k while u > 0and cur:
cur = cur.next
u -= 1 return dummy.next
TypeScript 代码:
functionreverseKGr0up(head: ListNode | null, k: number): ListNode | null { // reverse 的作用是将 root 后面的 k 个节点进行翻转 const reverse = function(root: ListNode | null, k: number): void { // 检查 root 后面是否有 k 个节点 let u = k, cur = root; while (u-- > 0 && cur != null) cur = cur.next; if (cur == null) return; // 进行翻转 let tail = cur.next, a = root.next, b = a.next; // 当需要翻转 k 个节点时,中间有 k - 1 个 next 指针需要翻转 while (k-- > 1) { let c = b.next;
b.next = a;
a = b;
b = c;
}
root.next.next = tail;
root.next = a;
}; let dummy = newListNode(-1);
dummy.next = head; let cur = dummy; while (cur != null) { reverse(cur, k); let u = k; while (u-- > 0 && cur != null) cur = cur.next;
} return dummy.next;
};
时间复杂度:会将每个节点处理一遍。复杂度为 O(n)
空间复杂度:O(1)
递归
搞懂了较难的「迭代哨兵」版本之后,常规的「递归无哨兵」版本写起来应该更加容易了。
需要注意的是,当我们不使用「哨兵」时,检查是否足够 k 位,只需要检查是否有 k−1 个 next 指针即可。
代码:
classSolution { public ListNode reverseKGr0up(ListNode head, int k) { intu= k; ListNodep= head; while (p != null && u-- > 1) p = p.next; if (p == null) return head; ListNodetail= head; ListNodeprev= head, cur = prev.next;
u = k; while (u-- > 1) { ListNodetmp= cur.next;
cur.next = prev;
prev = cur;
cur = tmp;
}
tail.next = reverseKGr0up(cur, k); return prev;
}
}
C++ 代码:
classSolution { public: ListNode* reverseKGr0up(ListNode* head, int k){ int u = k;
ListNode* p = head; while (p != NULL && u-- > 1) p = p->next; if (p == NULL) return head;
ListNode* tail = head;
ListNode* prev = head, *cur = prev->next;
u = k; while (u-- > 1) {
ListNode* tmp = cur->next;
cur->next = prev;
prev = cur;
cur = tmp;
}
tail->next = reverseKGr0up(cur, k); return prev;
}
};
Python 代码:
classSolution: defreverseKGr0up(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
u = k
p = head while p and u > 1:
p = p.next
u -= 1 ifnot p: return head
tail = prev = head
cur = prev.next
u = k while u > 1:
tmp = cur.next
cur.next = prev
prev, cur = cur, tmp
u -= 1
tail.next = self.reverseKGr0up(cur, k) return prev
TypeScript 代码:
functionreverseKGr0up(head: ListNode | null, k: number): ListNode | null { let u = k; let p = head; while (p != null && u-- > 1) p = p.next; if (p == null) return head; let tail = head, prev = head, cur = prev.next;
u = k; while (u-- > 1) { let tmp = cur.next;
cur.next = prev;
prev = cur;
cur = tmp;
}
tail.next = reverseKGr0up(cur, k); return prev;
};
模式匹配是枚举最常见的用法,最常见的是使用 switch / match / when 语句进行模式匹配:
Swift:
switch language { case .rust(let year): print(year) case .swift(let year): print(year) case .kotlin(let year): print(year)
}
Rust:
match language {
Language::Rust(year) => println!("Rust was first released in {}", year),
Language::Swift(year) => println!("Swift was first released in {}", year),
Language::Kotlin(year) => println!("Kotlin was first released in {}", year),
}
/** * 生成 2 的 n 次方个 HashCode 一样的字符串的集合 */ publicstatic ListhashCodeSomeList(int n){ List initList = new ArrayList(Arrays.asList(SEED)); for (int i = 1; i < n; i++) { initList = createByList(initList); } return initList; }
publicstatic ListcreateByList(Listlist){ List result = new ArrayList(); for (int i = 0; i < SEED.length; ++i) { for (String str : list) { result.add(SEED[i] + str); } } return result; } }
classSolution { publicintmaxPoints(int[][] points) { intn= points.length, ans = 1; for (inti=0; i < n; i++) { int[] x = points[i]; for (intj= i + 1; j < n; j++) { int[] y = points[j]; // 枚举点对 (i,j) 并统计有多少点在该线上, 起始 cnt = 2 代表只有 i 和 j 两个点在此线上 intcnt=2; for (intk= j + 1; k < n; k++) { int[] p = points[k]; ints1= (y[1] - x[1]) * (p[0] - y[0]); ints2= (p[1] - y[1]) * (y[0] - x[0]); if (s1 == s2) cnt++;
}
ans = Math.max(ans, cnt);
}
} return ans;
}
}
C++ 代码:
classSolution { public: intmaxPoints(vector<vector<int>>& points){ int n = points.size(), ans = 1; for (int i = 0; i < n; i++) {
vector<int> x = points[i]; for (int j = i + 1; j < n; j++) {
vector<int> y = points[j]; // 枚举点对 (i,j) 并统计有多少点在该线上, 起始 cnt = 2 代表只有 i 和 j 两个点在此线上 int cnt = 2; for (int k = j + 1; k < n; k++) {
vector<int> p = points[k]; int s1 = (y[1] - x[1]) * (p[0] - y[0]); int s2 = (p[1] - y[1]) * (y[0] - x[0]); if (s1 == s2) cnt++;
}
ans = max(ans, cnt);
}
} return ans;
}
};
Python 代码:
classSolution: defmaxPoints(self, points: List[List[int]]) -> int:
n, ans = len(points), 1 for i, x inenumerate(points): for j inrange(i + 1, n):
y = points[j] # 枚举点对 (i,j) 并统计有多少点在该线上, 起始 cnt = 2 代表只有 i 和 j 两个点在此线上
cnt = 2 for k inrange(j + 1, n):
p = points[k]
s1 = (y[1] - x[1]) * (p[0] - y[0])
s2 = (p[1] - y[1]) * (y[0] - x[0]) if s1 == s2: cnt += 1
ans = max(ans, cnt) return ans
TypeScript 代码:
functionmaxPoints(points: number[][]): number { let n = points.length, ans = 1; for (let i = 0; i < n; i++) { let x = points[i]; for (let j = i + 1; j < n; j++) { // 枚举点对 (i,j) 并统计有多少点在该线上, 起始 cnt = 2 代表只有 i 和 j 两个点在此线上 let y = points[j], cnt = 2; for (let k = j + 1; k < n; k++) { let p = points[k]; let s1 = (y[1] - x[1]) * (p[0] - y[0]); let s2 = (p[1] - y[1]) * (y[0] - x[0]); if (s1 == s2) cnt++;
}
ans = Math.max(ans, cnt);
}
} return ans;
};
时间复杂度:O(n3)
空间复杂度:O(1)
枚举直线 + 哈希表统计
根据「朴素解法」的思路,枚举所有直线的过程不可避免,但统计点数的过程可以优化。
具体的,我们可以先枚举所有可能出现的 直线斜率(根据两点确定一条直线,即枚举所有的「点对」),使用「哈希表」统计所有 斜率 对应的点的数量,在所有值中取个 max 即是答案。
Of course don't combine ALL of them, if the amount is HUGE. Say you have 1000 rows you need to insert, then don't do it one at a time. You shouldn't equally try to have all 1000 rows in a single query. Instead break it int0 smaller sizes.
Insert inside Mybatis foreach is not batch, this is a single (could become giant) SQL statement and that brings drawbacks:
some database such as Oracle here does not support.
in relevant cases: there will be a large number of records to insert and the database configured limit (by default around 2000 parameters per statement) will be hit, and eventually possibly DB stack error if the statement itself become too large.
Iteration over the collection must not be done in the mybatis XML. Just execute a simple Insertstatement in a Java Foreach loop. The most important thing is the session Executor type.
Internally, it still generates the same single insert statement with many placeholders as the JDBC code above.
MyBatis has an ability to cache PreparedStatement, but this statement cannot be cached because it containselement and the statement varies depending on the parameters. As a result, MyBatis has to 1) evaluate the foreach part and 2) parse the statement string to build parameter mapping [1] on every execution of this statement. And these steps are relatively costly process when the statement string is big and contains many placeholders.
[1] simply put, it is a mapping between placeholders and the parameters.
它是通过 Webpack Dev Server 来实现这个功能。当你在浏览器中发送请求时,请求会先被 Webpack Dev Server 捕获,然后根据你的代理规则将请求转发到目标服务器,目标服务器返回的数据再经由 Webpack Dev Server 转发回浏览器。这样就绕过了浏览器的同源策略限制,使你能够在本地开发环境中访问线上接口。
JustAuth 集成了诸如:Github、Gitee、微博、钉钉、百度、Coding、腾讯云开发者平台、OSChina、支付宝、QQ、微信、淘宝、Google、Facebook、抖音、领英、小米、微软、今日头条、Teambition、StackOverflow、Pinterest、人人、华为、企业微信、酷家乐、Gitlab、美团、饿了么、推特、飞书、京东、阿里云、喜马拉雅、Amazon、Slack和 Line 等第三方平台的授权登录。
classSolution { publicintmaxSubArray(int[] nums){ ints=0, m = 0, ans = -10010; for (int x : nums) {
s += x;
ans = Math.max(ans, s - m);
m = Math.min(m, s);
} return ans;
}
}
C++ 代码:
classSolution { public: intmaxSubArray(vector<int>& nums){ int s = 0, m = 0, ans = -10010; for (int x : nums) {
s += x;
ans = max(ans, s - m);
m = min(m, s);
} return ans;
}
};
Python 代码:
classSolution: defmaxSubArray(self, nums:List[int]) -> int:
s, m, ans = 0, 0, -10010 for x innums:
s += x
ans = max(ans, s - m)
m = min(m, s) return ans
TypeScript 代码:
functionmaxSubArray(nums: number[]): number{ let s = 0, m = 0, ans = -10010; for (let x of nums) {
s += x;
ans = Math.max(ans, s - m);
m = Math.min(m, s);
} return ans;
};
$ node mysql.js; [SELECT ERROR] - ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication
protocol requested by server; consider upgrading MySQL client
"http-nio-6071-exec-9" #82 daemon prio=5 os_prio=0 tid=0x00007fea9aed1000 nid=0x62 runnable [0x00007fe934cf4000]
java.lang.Thread.State: RUNNABLE
at org.springframework.core.annotation.AnnotationUtils.getValue(AnnotationUtils.java:1058)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory$AspectJAnnotation.resolveExpression(AbstractAspectJAdvisorFactory.java:216)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory$AspectJAnnotation.<init>(AbstractAspectJAdvisorFactory.java:197)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.findAnnotation(AbstractAspectJAdvisorFactory.java:147)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(AbstractAspectJAdvisorFactory.java:135)
at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice(ReflectiveAspectJAdvisorFactory.java:244)
at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice(InstantiationModelAwarePointcutAdvisorImpl.java:149)
at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.<init>(InstantiationModelAwarePointcutAdvisorImpl.java:113)
at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor(ReflectiveAspectJAdvisorFactory.java:213)
at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors(ReflectiveAspectJAdvisorFactory.java:144)
at org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(BeanFactoryAspectJAdvisorsBuilder.java:149)
at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:95)
at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:101)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:291)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:233)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1282)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1243)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at cn.hutool.extra.spring.SpringUtil.getBean(SpringUtil.java:117)
......
......
// 点击
d 0101050 c
u 0 c // 长按
d 0101050 c <wait in your own code>
u 0 c // 滑动
d 00050 c <wait in your own code>//需要拖拽加上等待时间
m 020050 c
m 040050 c
m 060050 c
m 080050 c
m 0100050 c
u 0 c