13. 罗马数字转整数
罗马数字包含以下七种字符: 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 的范围内。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/roman-to-integer
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一种方法的思路是可以直接检验字符串的前一位数字是否小于后一位数字,因为比如IV这样的字符串,就是V-I,当然该函数这样需要满足的前提条件是,这些输入的罗马数字都是合法的。
1.class Solution {
public int romanToInt(String s) {
int sum=0;
int prenum=getvalue(s.charAt(0));
for(int i=1;i<s.length();i++)
{
if(prenum<getvalue(s.charAt(i)))
{
sum=sum-prenum;//对于IX这类情况而言,prenum<getvalue(s.charAt(i)),prenum要被减去
}
else
{
sum=sum+prenum;
}
prenum=getvalue(s.charAt(i));
}
sum=sum+prenum;//在最后的数字肯定是被加上的
return sum;
}
private int getvalue(char ch)
{
switch(ch)
{
case'I':return 1;
case'V':return 5;
case'X':return 10;
case'L':return 50;
case'C':return 100;
case'D':return 500;
case'M':return 1000;
default:return 0;
}
}
}
**2.第二种方法利用哈希表,将特定情况在哈希表中列举**
class Solution {
public int romanToInt(String s) {
Map<String, Integer> map = new HashMap<>();
map.put("I", 1);
map.put("IV", 4);
map.put("V", 5);
map.put("IX", 9);
map.put("X", 10);
map.put("XL", 40);
map.put("L", 50);
map.put("XC", 90);
map.put("C", 100);
map.put("CD", 400);
map.put("D", 500);
map.put("CM", 900);
map.put("M", 1000);//这里将所有的单个数以及两个数的特例情况列出
int ans = 0;
for(int i = 0;i < s.length();) {
if(i + 1 < s.length() && map.containsKey(s.substring(i, i+2))) {
ans += map.get(s.substring(i, i+2));//这里是判断两个字符的情况在哈希表中是否存在
i += 2;
} else {
ans += map.get(s.substring(i, i+1));//这里是单个字符
i ++;
}
}
return ans;
}
}
注:通过这题的训练,我了解到了string中的charAt方法
20. 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
private static final Map<Character,Character> map = new HashMap<Character,Character>(){{
put('{','}'); put('[',']'); put('(',')'); put('?','?');
}};
public boolean isValid(String s) {
if(s.length() > 0 && !map.containsKey(s.charAt(0))) return false;//当字符串长度大于0,并且哈希表中不包含这个字符串的第一个字符,那么返回false;
LinkedList<Character> stack = new LinkedList<Character>() {{ add('?'); }};//初始化链表,size为1
for(Character c : s.toCharArray()){
if(map.containsKey(c)) stack.addLast(c);//这里应该是加入了左侧的值,即(,{,[
else if(map.get(stack.removeLast()) != c) return false;//如果从栈中得到的最后一个元素的值在哈希表中映射和哈希表中的不一致,那么就返回false
}
return stack.size() == 1;
}
}
注:通过本题的训练,我了解到了java中的character类
关于Character类:
Character 类用于对单个字符进行操作。
Character 类在对象中包装一个基本类型 char 的值
关于该类的一些详细的方法:
https://www.runoob.com/java/java-character.html
21. 合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
迭代法:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead=new ListNode(-1);//初始化一个新的节点,赋值为-1;
ListNode prev=prehead;//把头结点的值暂时赋值给prev
while(l1!=null&&l2!=null)
{
if(l1.val<=l2.val)
{
prev.next=l1;
l1=l1.next;
}
else
{
prev.next=l2;
l2=l2.next;
}
prev=prev.next;//比如当列表中加入一个元素1,那么pre需要移动到这个元素上,继续进行后续的比较
}
prev.next=l1==null?l2:l1;//判断l1或者l2是否还是空的,不是空的就加载prev后
return prehead.next;//这个是最初始的节点,返回他之后的链表
}
}
38. 外观数列
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-and-say
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public String countAndSay(int n) {
String str="1";
for(int i=2;i<=n;i++)
{
StringBuilder builder = new StringBuilder();//对于每一行都要重新构件一个可以装入一个新的字符串的stringbulider
char pre=str.charAt(0);//先将当前已经得到的str字符串的第一个字符赋值给pre
int count=1;//统计某个字符的字符数
for(int j=1;j<str.length();j++)
{
char cur=str.charAt(j);//记录当前的字符是什么
if(pre==cur)
{
count++;//如果当前字符和前一个字符相同,那么该字符的总数加1
}
else
{
builder.append(count).append(pre);//先把count个pre放入字符串
pre=cur;
count=1;//新的字符的个数变为1
}
}
builder.append(count).append(pre);//加上最后一个字符的个数和相应的字符值
str=builder.toString();
}
return str;
}
}
注:通过该题的训练,我了解到了java中的stringbuilder类
关于StringBuilder:
一些常用方法在这个链接中:https://blog.csdn.net/x83853684/article/details/82081658
67. 二进制求和
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1 和 0。
示例 1:
输入: a = “11”, b = “1”
输出: “100”
示例 2:
输入: a = “1010”, b = “1011”
输出: “10101”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-binary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这里的方法是直接相加法
class Solution {
public String addBinary(String a, String b) {
StringBuilder ans = new StringBuilder();
int ca = 0;//进位
for(int i = a.length() - 1, j = b.length() - 1;i >= 0 || j >= 0; i--, j--) {
int sum = ca;
sum += i >= 0 ? a.charAt(i) - '0' : 0;
sum += j >= 0 ? b.charAt(j) - '0' : 0;//对于a,b来说,当长度不一致时,更短的那个,最后sum都加上0
ans.append(sum % 2);
ca = sum / 2;
}
ans.append(ca == 1 ? ca : "");
return ans.reverse().toString();
}
}