题目

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0。

示例 1:

输入: a = “11”, b = “1”
输出: “100”
示例 2:

输入: a = “1010”, b = “1011”
输出: “10101”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-binary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路1

第一次写这道题,怎么感觉之前做过,字符串二进制进位
使用简单的字符串一个个比较,
第一次问题在字符串拼接,使用insert但没有插入到头部
效率比较低

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Solution {
public String addBinary(String a, String b) {
boolean up = false;
int aLength = a.length();
int bLength = b.length();
int strLength = aLength >= bLength ? aLength : bLength;
if(aLength > bLength){
b = String.join("", Collections.nCopies(strLength - bLength, "0")) + b;
}else if(bLength > aLength){
a = String.join("", Collections.nCopies(strLength - aLength, "0")) + a;
}
char[] aArray = a.toCharArray();
char[] bArray = b.toCharArray();
StringBuilder sb = new StringBuilder();
for(int i = strLength -1 ; i >= 0 ; i--){
char aChar = aArray[i];
char bChar = bArray[i];
if(aChar == '1' && bChar == '1'){
if(up){
sb.insert(0,"1");
}else{
sb.insert(0,"0");
}
up = true;
}else if(aChar == '0' && bChar == '0'){
if(up){
sb.insert(0,"1");
}else{
sb.insert(0,"0");
}
up = false;
}else{
if(up){
sb.insert(0,"0");
up = true;
}else{
sb.insert(0,"1");
up = false;
}
}
}
if(up){
sb.insert(0,"1");
}
return sb.toString();
}
}

思路2

第二种算法,看别人的答案,思路跟之前相似,但实现不同,不用一堆id判断,用字符与‘0’相减直接得数字
自己写得时候,等于0没有想到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public String addBinary(String a, String b) {
int ans = 0;
StringBuilder sb = new StringBuilder();
for(int i = a.length()-1 ,j = b.length()-1 ; i>=0 || j>=0 ; i-- ,j--){
int sum = ans;
sum += (i >= 0 ? a.charAt(i)- '0' : 0);
sum += (j >= 0 ? b.charAt(j) - '0': 0);
sb.append(sum % 2);
ans = sum /2;
}
sb.append(ans == 1? ans : "");
return sb.reverse().toString();
}
}

最近在学习c语言,本以为有了java的基础,以前在学校还学习过,c语言应该很简单,但我发现不是,还是有一些陌生的概念没有理解。
C语言的本身很精炼,与java相比,java有些臃肿,什么都包括。
基础的概念比如,类型、运算符,表达式,控制流。
比较特殊的,函数与程序结构,指针与数组,结构。
剩余是输入与输出和一些系统接口。
都通用的就不提了,主要是一些特殊的概念,比如函数中的头文件,C预处理器等。
指针是c语言特点所在,也是难点所在,灵活但容易出错。
结构类似面向对象的功能,将一些属性包装在一起。

学习一个东西,不能想着一下全学会,先快速入门,然后不断登台阶,与实际结合,解决问题,这样才是关键。不能单学理论,也不能直接实践,但学理论容易陷入无用的境地,单单实践,容易浪费时间不断试错,不同阶段,两个结合起来效果最佳。

人的成长从吴军老师那学来的方法,三板斧破四困境,四困境是简单重复,习惯性失败,林黛玉式困境和狗熊掰棒子。
第一板斧,愿景-目标-道路。从战略到战术,都要具体到细节,才能实施。平时我们每年都会有些计划,但很多计划没有落实到细节,虽然知道很重要但一直都没有做,因为没有道路,生活还是照旧,目标永远达不成。这个最近体会很深,比如我认为C语言很重要,也制定了目标,就是学会c语言,这是通向底层的必经之路,但我们目标不够明确,怎么算学会c语言,c语言有哪些部分,都是什么,有哪些不同的等级,当时都完全不清楚。等我开始执行的时候,发现c语言不会的东西很多,短时间完全执行不完,再有挫折一打击,这个目标可能就被搁置,然后不了了之。还有一点就是没有具体道路到每天,可能一有紧急的事情就把原来的时间占用,最后都只做紧急的事情,很多重要的事情都被搁置。
这一点我是体会越来越深,所以从战略到战术,都要具体,愿景的不能等级,具体的目标,每天如何安排时间去完成都要细化,这样具体的目标才能执行,笼统的概念没办法达成,生活中很多事情都是同样的道理。

比如我想改掉每晚去看视频的习惯,视频没什么营养,我也认识到这样是浪费时间的,但我没有安排具体的替换习惯,所以,即使知道这样不对,我没有其他选择,那有了时间照旧,还是看视频,那会给我放松,所以道路就是具体的方法。安排越细节,成功可能性越高。

学习目标要等级,如何算晋级,不能简单的重复,要不断升级,我经常碰见学不下去的情况,那最好的方法就是从起点重现开始,这也是我发现的最好的学习方式,不能一遍一遍的重复不会的东西,确实能理解提高,尤其是学习困难的东西,效果更是明显,从第一次的一脸懵逼,到有点明白,真的很振奋。所以这是不是就是学习的真谛,不断重复,失败了从起点重新来过。学习如此生活亦如此,就是个不断从起点出发,经历挫折,不断成长的过程,所以失败不可怕,这是常态。

最近对于年龄的危机,越来越明显了,之前认为自己还小,还有时间,但最近年过30,而且马上就过了互联网的最佳年龄了,体力大不如前,如果没有什么特殊的能力,那肯定不如年轻人。年龄与能力不是必然挂钩,年龄不能控制,能力可以培养。

现在社会节奏越来越快,人们好像没有时间,一步不停的加紧追赶,我也是自认为很努力的人,总怕浪费时间,周末早早醒来,想看看书,但实际呢,没有什么进步,时间虽然抓的很紧,但都是花在无关紧要的事情上,或者当时看来紧急的事情上,随着时间的流逝,没有什么东西剩下,所以随着时间一场空。
人对于长期的目标,很难很好的记住,时间的流逝,慢慢的人就淡忘了,被生活的琐事冲刷,突然有了新的目标,这些都会不断冲击原来的长期目标。淡忘就是长期目标最大的敌人,但对于短平快的刺激,人们就很适应,时间短快速开始快速结束,不会用很多时间,快速反馈,很快就有结果。目标快速达成不断刺激的人们进入,抖音代表的短视频,微博代表的短新闻,得到的听别人解读书,B站上的电影快速介绍,都搓中人性的弱点,我也是这样一路走来,我特别喜欢看电影快速介绍,既花很少的时间,又看过很多电影,虽然每次时间很多,但让人上瘾,一下就花了2,3个小时不自知。但想想有什么都没留下来,我基本记不住讲了什么。
但时间短并不是碎片化学习的主要问题,在人们习惯于容易获得的快乐后,是否还能吃苦去获取真正重要的东西。比如一个人吸毒很难戒掉,如果可以轻易体会极致的快乐,为什么要花时间去体验人生。要明白什么才是事实,很多知识不是短时间就能学会的,要花长时间去不断学习,但如果你养成了快速获取知识,只有这一种方式你能接受,那深度的知识你没有获取的方式,任何东西都是分层的,不同层次对应不同的方法。比如从简到奢易,从奢到简难就是这个道理。只是需要深度连接,互相关联,才能形成自己的体系、积累。这样的学习方式,让人们不得不花大量时间去链接,形成体系,也是这种学习方式造成了,时间短的碎片化学习,不能完全替代系统学习。这两种有不同的应用场景。碎片化学习,适用于短暂的了解,扩大知识面。深度系统学习,适合积累知识,符合收益最大的原则。
尽量拒绝短平快的方式,除非必须需要,省下来时间给深度学习。

今天下午体会了一把,快节奏游戏的快感,消消乐玩了2个小时,一局3分钟,节奏很快,失败重新来过的成本很小,导致一直想着反正时间短,下一局就不玩了,但就这么一局一局2个小时过去了,昨天我女朋友玩了一下午我还感觉不可思议,今天自己也这样,利用了人性的弱点,喜欢短平快的快感,昨天看了耗子叔对于学习的态度,对于现在世界的发展看法印象很深刻,快餐文化,追求短平快,给人一种虚假的满足感。对于李笑来之前说的,观点不光正确,还要与别人不同,差异越大,对于你越重要。因为这是你的成功点,但要保证是正确的,不能追求不同,那样是本末倒置。
因为人性的弱点,追求短平快的快感,所以社会越来越流行这样的文化,大家越来越浮躁,希望快速成名,快速成功,所以很多人贩卖成功,贩卖知识,但正确的事情确实反人性的,需要花很多时间,很多精力去钻研知识。快餐文化经常让人感觉空虚,因为根基是空的,只是表面繁荣
历史有一些趋势不可逆转,知识越来越多,生活节奏越来越快。
对于信息的处理越来越影响大,人的生命有限,不可能会所有知识,但人又很贪心,不想放弃,所以通过一些快节奏的方式,听书,短视频,微博,朋友圈来快速获取信息,来给自己一种满足感。但因为时间短,信息量少,所以会有很多前提条件和解释过程省略了,让你只能从中学习结论。
当前社会人性的弱点会被利用,反人性可以让你不被操纵,收获不同的能力。
学习不光学知识,还学习方法,学习体系,知识无限,掌握方法就能从一点迁移到另外一点,学深可以理解本质,然后迁移,看到不同的风景。

第2章 信息的表示和处理

这周完成一遍阅读,但很多地方不懂,原来有些底子,但书中很多东西与原来的学习的不太一样,将了很多数学原理的部分。
信息的存储
讲解十六进制的表示法,寻址与字节顺序,怎么表示字符串,代码与布尔代数,同时介绍位级运算,逻辑运算和移位运算。
整数的表示
整形数据类型,无符号数的编码,补码编码,有符号和无符号的转换,扩展一个数字的位表示,截断数字
整数运算
无符号加分,补码加法,补码的非,无符号乘法,补码乘法,乘以常数,除以2的幂
浮点数
二进制的小数,IEEE浮点表示,数字示例,舍入,浮点运算,
可能会有第二遍阅读,虽然还有很多数学原理部分不懂,但原来有些底子,如果后面用到,再重新读一遍。

这一章讲的信息是如何在计算机上表示的,2进制与16进制的转换,整数,浮点数,字符串等信息的表示,运算方法

最近基于jhipster脚手架开发spring cloud的项目,突然感觉软件工程真的是很复杂的东西,从上倒下都要了解一点,如果那部分一点不懂,出了问题就不能搞定,要花很多时间试错,无法思考解决方法,只能简单的试错,这次就是gradle拉包有问题,有一个同事搞了一个星期,还有些没搞定,看着他一点点从边缘摸索试错,这就是编译工具不了解,导致遇到这部分一点都没法思考,连找问题都不知道怎么找。
最近也再思考职业规划,发现真的到了瓶颈了,虽然也有很多东西可以继续学习,但如果再找不到真正缺失的东西,会再多也不能突破瓶颈,原来以为自己已经不错了,框架上的东西自己也能做,但这么长时间看来,还是井底之蛙了,与那些在大公司起点就很高的人,有着天壤之别。之前以为自己基础好了就可以了,所以一点点开始复习基础,但现实一次次打脸,基础是内功,让你成长很快,走的很深很远,但公司是要生产力,你用时间换钱,工作这么长时间来了还不能干活,很多东西不会用,你都工作这么长时间,也没什么突出项,连常用工具都不会,我还会找你?要看清本质,大公司想要能干活的人太多了,所以才要求基础,起码招来的人更好,后面能走的更远。
但从另外一个角度看,不能市面上出了一个新技术你就去学习,那样也是很低效的,新东西层出不穷,你的时间有限,还是要从底层从抽象学起,这样才高效,不会被时间淘汰。即使有了新技术有以前的抽象基础,不会过时,只要对比学习差异就行。现在我太多分布式的基础不会,不说原理不会,连用都没用过,这也是我总结之前失败的原因。
要有自己的作品,开源的项目,或者能参与过开源的项目。
要知识体系全面,会流行的技术,同时懂得基础。既能干活,又能分析问题。

总结第三章,程序的机器级表示
介绍了C语言抽象层下面的机器级结构
主要分为几部分,数据分为整数与浮点数,两者分别有不同的寄存器,原理相同
以整数介绍为主
数据的格式,字节,字,双字,四字
然后是访问信息,对于数据的访问与加载,有操作数指示符,寄存器,内存,直接数的表示方法
传送指令 mov,压入和弹出栈指令pop,push(这个为后面过程铺垫)
接着是算术与逻辑,一元,二元操作,移位等。
接着是控制,几个条件判断的寄存器,命令访问条件码,跳转命令jump,2种实现条件分支的方法,一种是条件控制,类似jump,goto,一种是用条件传送,第二种更符合现在处理器高效的风格,因为不需要跳转,局部性原理,效率更高,但只有部分符合条件,不是所有情况都能适用。
然后就是控制的实现,一种是do-while,while,for等循环,1个是switch的实现。
下一部分是过程,如果寄存器不够或者的方法间互相调用,就会用到过程。主要分为三部分,传递控制,传递数据,和分配和释放内存。
使用%rsp栈指针,$rip来指示栈帧的位置,是用call和ret转移控制。
下一部分是数组,主要是指针的处理,嵌套数组,定长数组,变长数组
然后是异构数据结构,结构struct,联合Union
最后一部分是浮点数,与整数原理相通。

题目

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
示例 1:
输入: 3
输出: “III”
示例 2:
输入: 4
输出: “IV”
示例 3:
输入: 9
输出: “IX”
示例 4:
输入: 58
输出: “LVIII”
解释: L = 50, V = 5, III = 3.
示例 5:
输入: 1994
输出: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.
有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路1, 看别人思路
将 数字与字母对应存储在数组中,然后要求的数字,依次从最大的开始减,最后就得到结果
执行用时 :32 ms, 在所有 Java 提交中击败了11.85%的用户 内存消耗 :42 MB, 在所有 Java 提交中击败了74.61%的用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public String intToRoman(int num) {
int[] rome = new int[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};
Map<Integer,String> map = new HashMap<>();
map.put(1000,"M");map.put(900,"CM");map.put(500,"D");
map.put(400,"CD");map.put(100,"C");map.put(90,"XC");
map.put(50,"L");map.put(40,"XL");map.put(10,"X");
map.put(9,"IX");map.put(5,"V");map.put(4,"IV");map.put(1,"I");
int i = 0;
StringBuilder sb = new StringBuilder();
while(num > 0){
if(num >= rome[i]){
num = num - rome[i];
sb.append(map.get(rome[i]));
}else{
i++;
}
}
return sb.toString();
}
}

servlet简单说就是处理网络请求的接口,java将处理网络请求的过程抽象处理,将复杂的网络处理交给servlet容器,程序员只需要实现接口就能简单的实现处理请求

1
2
3
4
5
6
7
8
9
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;

public String getServletInfo();

public void destroy();

一个有5个接口,一个初始化init,一个结束销毁destroy,getServletConfig 获取配置,getServletInfo获取servlet信息,真正处理网络请求的就是service。
要实现http请求,可以继承HttpServlet,他是http协议的一个实现,然后覆盖doGet与doPost方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class XmlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("XmlServlet 在处理 get() 请求....");
PrintWriter out = resp.getWriter();
resp.setContentType("text/html;charset=utf-8");
out.println("<strong>My Servlet!</strong>
");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("MyServlet在处理 post()请求...");
PrintWriter out = resp.getWriter();
resp.setContentType("text/html;charaset=utf-8");
out.println("<strong>My Servlet</strong>
");
}
}

写2个servlet标签,servlet-name相同,一个引入刚才写的class,一个匹配访问地址

1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>xmlServlet</servlet-name>
<servlet-class>servlet.XmlServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>xmlServlet</servlet-name>
<url-pattern>/xmlservlet</url-pattern>
</servlet-mapping>

一个简单的servlet就完成了,然后放入到tomcat对应文件的位置
XmlServlet放在tomcat的目录下,webapps/{you apps name}/WEB-INF/classes/{package path} 路径下,web.xml 放在与WEB-INF同级目录内