剑指offer53
统计一个数字在排序数组中出现的次数。
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
- 二分查找
剑指offer56
一个整型数组 nums
里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
- 一个数如果是和0异或则得到其本身,和自己异或则为0.
- 如果问题改成除了一个数字之外,其他数字都出现了两次,那么直接用0和数组中所有数字都异或一轮,剩下的就是只出现了一次的数字 。如果是有两个只出现了两次的数字,则需要对原先的数组进行分组,每组只有一个只出现了一次的数字和若干对出现两次的数字,这样就转换成了上面一种情况。方法是对两个只出现一次的数相异或的结果,找到最低位为1的数字,这一位为1表明那两个数在这位上一个为1一个为0,对于整个数组而言,根据在这一位是否为1来进行分组。
剑指offer56Ⅱ
在一个数组 nums
中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
-
直接Hashmap。
-
一种新的遍历方式 for(Map.Entry<Integer,Integer> entry:hashmap.entrySet())
entry.getKey():返回键值,entry.getValue():返回值
剑指offer58Ⅱ
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
- String.substring()直接秒
剑指offer60
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
-
第一次用的dfs,res[i]存放的是点数之和为i时有几种可能。但是用时比较长。
public void dfs(double[]res,int n,int sum,int iter) { if(iter==0) { res[sum-n]++; return; } for(int i=1;i<=6;i++) dfs(res,n,sum+i,iter-1); }
-
动态规划。考虑n个骰子和n-1个骰子每个总数可能之间的关系。dp[i][j]表示i个骰子总数为j时的可能情况,则可以得到状态转移方程dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+…+dp[i-1][j-6],表示前n-1个骰子掷出和为j-k时,这时候第n个骰子只需要掷出k即可。(1<=k<=6)
-
Math.pow(a,b):指数算式,表示 a b a^b ab
剑指offer65
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号
-
要求a+b首先要弄清楚a^b异或得到其实是a+b每一位上都没有进位相加得到的结果,而a&b得到的结果中为1的那一位表明这一位需要向前一位进位1,因此有a+b=a^b+(a&b)<<1,虽然还是转换成了加法,但是后者可以递归实现,当进位为0时表明此时没有进位,a^b=a+b得到结果。
class Solution { public int add(int a, int b) { if(b==0) return a; return add(a^b,(a&b)<<1); }}
206.反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
-
一开始用的头插法进行原地逆置,后来发现他这个题目给的是头指针不是头结点,所以手动new一个头结点ListNode h1=new ListNode(0,head);用头插法时要注意,第一次插入时head.next是等于p的,如果这时候令p.next=head.next会出现环,导致Error - Found cycle in the ListNode错误。因此第一次插入要进行判断:
if(h1.next!=p) p.next=h1.next; else p.next=null;
-
另一种思路是不动结点,每次仅改变链表中两个结点之间next指向,最终全部都反着指。初始res设置为空,好处在于不用考虑第一个结点(最终变成next为空的最后一个节点)的情况。
146.LRU缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存约束的数据结构。
-
难点在于用什么样的数据结构来记录Cache缓存中每个结点的访问状态。一开始用的ArrayList来保存每个key,容器中重载了两种remove()方法,分别对应着两种场景:
-①缓存满时需要逐出最久未使用的结点时,可以直接通过索引下标删除cache.remove(0)
-②访问一个已有结点需要更新该节点的使用状态时,可以先移除该key,再add()加入到缓存数组的尾部,这样便实现了最近使用状态的更新。此时移除是通过key值删除cache.remove(Integer.valueOf(key))
最后还需要考虑的是当新加入的结点仅仅需要更新value值情况,这时候对应cache对这个key值使用状态更新所采取的操作会有不同。 -
另一种是用双向链表来记录使用状态。比较难想到的点是hashmap里面value存放的不是结点值,而是这个key存放在双向链表的结点(位置),这样每次需要根据key来找到存放该结点状态的位置进行更新时,就不要遍历整个双向链表才找得到,否则单单是使用双向链表的话查询复杂度就为O(n)不满足O(1)。同时双向链表的属性除了要有value,还需要有对应的key,只有这样当缓存溢出时,才能通过head.key删去哈希表中的key结点。
3.无重复字符的最长字串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
- 用hashmap来记录字符是否出现。len记录的是每次for循环以s.charAt(i)字符为右端点的最长子串长度。如果当前字符未出现在hashmap中,则将其添加到hashmap并且窗口向右移动;而如果当前字符出现过,则左窗口移动(hashmap删除元素),直至当前字符已经从hashmap删去。
- Character和Integer,Long是char和int,long的包装类,是一个类,而char和int,long是基本数据类型,基本数据类型默认值是0。包装类可以拆包成基本数据类型,基本数据类型可以包装成类。类似于类和类内属性的关系。
Integer转int:Integer.intValue()
int转Integer:Integer.valueOf(int)
Integer封装了int类型的最大值最小值:Integer.MIN_VALUE, Integer.MAX_VALUE
今日总结
刷题