剑指 Offer 46. 把数字翻译成字符串
题目:
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,11 翻译成 “l”,25 翻译成 “z”。一个数字可能有多个翻译。
请实现一个函数,用来计算一个数字有多少种不同的翻译方法
题解(动态规划):
清晰图解
public int translateNum(int num) {
String s = String.valueOf(num);int a = 1, b = 1;for(int i = 2; i <= s.length(); i++) {
String tmp = s.substring(i - 2, i);int c=tmp.compareTo("10") >= 0 && tmp.compareTo("25") <= 0 ? a + b : a;b = a;a = c;}return a;}
剑指 Offer 48. 最长不含重复字符的子字符串
题目:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
题解(滑动窗口):
1.使用两个下标值slow
和fast
来维护滑动窗口,fast不断前进来遍历字符串,并将字符及其下标存入map中;
2.对于每次循环,均需要判断当前fast指针所指字符在map中是否存在,若存在则将slow指针移动至该字符上次出现的位置,此时需要注意:该字符在map中存在并不代表此时窗口内存在重复字符,比如abba
,因此 slow=Math.max(slow,map.get(array[fast])+1)
;
3.每次循环均需要更新max值。
public int lengthOfLongestSubstring(String s) {
char[] array = s.toCharArray();int fast=0,slow=0,max=0;Map<Character,Integer> map = new HashMap<>();while (fast<s.length()){
if (map.containsKey(array[fast])){
slow=Math.max(slow,map.get(array[fast])+1);}map.put(array[fast],fast);fast++;max = Math.max(max,fast-slow);}return max;}
剑指 Offer 18. 删除链表的节点
题目:
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。
题解:
复制头节点给temp节点,向后遍历,如果temp的下一个节点是所要找的,执行 temp.next=temp.next.next
调整指针,直接break;返回头节点。
public ListNode deleteNode(ListNode head, int val) {
if (head.val==val){
return head.next;}ListNode temp = head;while (temp!=null){
if (temp.next.val==val){
temp.next=temp.next.next;break;}temp = temp.next;}return head;}
剑指 Offer 22. 链表中倒数第k个节点
题目:
输入一个链表,输出该链表中倒数第k个节点。
例如:给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.
题解1(栈):
通过遍历链表将所有节点压栈,然后向外弹栈,返回第k
个节点。
public ListNode getKthFromEnd(ListNode head, int k) {
Stack<ListNode> stack = new Stack<>();while (head!=null){
stack.add(head);head=head.next;}for (int i=0;i<k-1;i++){
stack.pop();}ListNode res = stack.pop();return res;}
题解2(双指针):
1.定义两个节点指针slow
和fast
,初始均指向头节点;
2.保持slow
位置不变,向前移动fast
,形成一个长度为k
的窗口;
3.在fast
指针未到达最后一个时,两个指针维持长度未k
的窗口向前滑动;
4.当fast
指针到达尾部时,此时slow
指针所指位置即为倒数第k
个,返回即可。
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode slow = head;ListNode fast = head;//创造一个区间为k的滑动窗口for (int i=0;i<k;i++){
fast=fast.next;}//两个指针一起向后移动while (fast!=null){
fast=fast.next;slow=slow.next;}return slow;}
剑指 Offer 25. 合并两个排序的链表
题目:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
题解:
获取全部的节点值并存入list中,将排序之后的list转换为链表。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//获取全部的节点值并存入list中List<Integer> list = new ArrayList<>();while (l1!=null){
list.add(l1.val);l1=l1.next;}while (l2!=null){
list.add(l2.val);l2=l2.next;}Collections.sort(list);//将排序之后的list转换为链表ListNode head = new ListNode(0);ListNode temp = head;for (int i=0;i<list.size();i++){
ListNode node = new ListNode(list.get(i));temp.next=node;temp=temp.next;}return head.next;}
剑指 Offer 52. 两个链表的第一个公共节点
题目:
输入两个链表,找出它们的第一个公共节点。
题解:
1.A和B分别在其所在链表进行遍历,判断是否相等;
2.若节点A为空时,A和B还不相等,则另A从头开始遍历B链表;同理当B为空时,B继续从头开始遍历A链表3.当A和B相等时跳出循环有两种情况:一种是真的找到了公共节点,另一种是二者均走完了两个链表并且两个链表无公共节点,二者均为null
;
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode headATemp = headA;ListNode headBTemp = headB;while (headA!=headB){
if (headA==null){
headA=headBTemp;}else {
headA=headA.next;}if (headB==null){
headB=headATemp;}else {
headB=headB.next;}}return headA;}
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
题目:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
题解1:
创建等长的数组res
,遍历数组将奇数从前往后开始存储,偶数从后往前存储。
public int[] exchange(int[] nums) {
int[] res = new int[nums.length];int i=0;//从前往后移动 存储奇数int j= nums.length-1; //从后往前移动 存储偶数for (int m=0;m<nums.length;m++){
int a = nums[m];if (a%2==0){
res[j]=a;j--;}else {
res[i]=a;i++;}}return res;}
题解2(双指针):
1.定义两个下标i
和j
,其中i
从前往后寻找偶数,j
从后往前寻找奇数;
2.如果i
找到了偶数,则停止不再继续前进,等待j
找到奇数然后二者互换;
同理,如果j
找到了奇数,则停止不再继续前进,等待i
找到偶数然后二者互换;
直至i>=j
,循环结束。
public int[] exchange(int[] nums) {
int i=0;//从前往后移动int j= nums.length-1; //从后往前移动while (i<j){
if (nums[i]%2==0&&nums[j]%2!=0){
int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}if (nums[i]%2!=0){
i++;}if (nums[j]%2==0){
j--;}}return nums;}
剑指 Offer 57. 和为s的两个数字
题目:
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
题解(双指针):
1.定义两个下标变量i
和j
,分别初始化为0和length-1
;
2.当i<j时,判断此时二者的和与target的关系:
如果大于的话,则 j - -;如果小于则 i + +;如果相等则break。
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];int i=0;int j=nums.length-1;while (i<j){
if (nums[i]+nums[j]>target){
j--;}if (nums[i]+nums[j]<target){
i++;}if (nums[i]+nums[j]==target){
res[0]=nums[i];res[1]=nums[j];break;}}return res;}
剑指 Offer 58 - I. 翻转单词顺序
题目:
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
题解:
1.掉字符串开头和结尾的空格,按照单个或者多个空格进行划分;
2.遍历数组并入栈,弹栈并进行字符串拼接。
public String reverseWords(String s) {
Stack<String> stack = new Stack<>();String m = s.trim();//去掉字符串开头和结尾的空格String[] array = m.split("\\s+");//按照单个或者多个空格进行划分//遍历数组并入栈for (int i=0;i<array.length;i++){
stack.add(array[i]);}String res ="";//弹栈并进行字符串拼接while (!stack.isEmpty()){
res = res +" "+stack.pop();}return res.trim();}
最近的天气 让我觉得每次开门都像在开冰箱!