32.上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7],3
/ \
9 20
/ \
15 7
返回:[3,9,20,15,7]
提示:
节点总数 <= 1000
class Solution {
public int[] levelOrder(TreeNode root) {
//广度优先遍历-队列实现
Queue<TreeNode> queue=new LinkedList<>();
List<Integer> list=new ArrayList<>();
if(root==null){
return new int[0];
}
TreeNode temp=root;
queue.offer(temp);
while(!queue.isEmpty()){
TreeNode curr=queue.poll();
list.add(curr.val);
if(curr.left!=null){
queue.offer(curr.left);
}
if(curr.right!=null){
queue.offer(curr.right);
}
}
int size=list.size();
int[] res=new int[size];
for(int i=0;i<size;i++){
res[i]=list.get(i);
}
return res;
}
}
32.从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7],3
/ \
9 20
/ \
15 7
返回其层次遍历结果:[
[3],
[9,20],
[15,7]
]
提示:
节点总数 <= 1000
注意:本题与主站 102 题相同:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root==null){
return new ArrayList<>();
}
List<List<Integer>> res=new ArrayList<>();
List<Integer> temp;
Queue<TreeNode> queue=new LinkedList<>();
TreeNode t=root;
queue.offer(t);
while(!queue.isEmpty()){
int n=queue.size();
temp=new ArrayList<>();
while(n>0){
TreeNode tn=queue.poll();
temp.add(tn.val);
n--;
if(tn.left!=null){
queue.offer(tn.left);
}
if(tn.right!=null){
queue.offer(tn.right);
}
}
res.add(temp);
}
return res;
}
}
32.请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],3
/ \
9 20
/ \
15 7
返回其层次遍历结果:[
[3],
[20,9],
[15,7]
]
提示:
节点总数 <= 1000
!!!不能想当然的用栈 ,用栈的代码如下:
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//不用队列用栈
if(root==null){
return new ArrayList<>();
}
Deque<TreeNode> dq=new ArrayDeque<>();
List<List<Integer>> res=new ArrayList<>();
List<Integer> temp;
TreeNode t=root;
dq.addLast(t);
while(!dq.isEmpty()){
temp=new ArrayList<>();
int size=dq.size();
while(size>0){
TreeNode tn=dq.pollLast();
temp.add(tn.val);
size--;
if(tn.left!=null){
dq.addLast(tn.left);
}
if(tn.right!=null){
dq.addLast(tn.right);
}
}
res.add(temp);
}
return res;
}
}
根据层的奇偶,判断加到头还是加到尾,判断层的奇偶?
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
if(root != null) queue.add(root);
while(!queue.isEmpty()) {
//用linkedlist!!奇数就加前面,偶数加后面,无形中完成颠倒。
LinkedList<Integer> tmp = new LinkedList<>();
for(int i = queue.size(); i > 0; i--) {
TreeNode node = queue.poll();
if(res.size() % 2 == 0) tmp.addLast(node.val); // 偶数层 -> 队列头部
else tmp.addFirst(node.val); // 奇数层 -> 队列尾部
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
res.add(tmp);
}
return res;
}
}
用res的尺寸判断!!!
44.数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:输入:n = 11
输出:0
限制:
0 <= n < 2^31
注意:本题与主站 400 题相同:https://leetcode-cn.com/problems/nth-digit/来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:输入:n = 11
输出:0
限制:
0 <= n < 2^31
注意:本题与主站 400 题相同:https://leetcode-cn.com/problems/nth-digit/
这规律有点子恶心。。
class Solution {
public int findNthDigit(int n) {
int digit = 1;
//int会越界
long start = 1;
long count = 9;
while (n > count) { // 1.
n -= count;
digit ++;
start *= 10;
count = digit * start * 9;
}
long num = start + (n - 1) / digit; // 2.
return Long.toString(num).charAt((n - 1) % digit) - '0'; // 3.
}
}
61.从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
示例 1:
输入: [1,2,3,4,5]
输出: True
示例 2:
输入: [0,0,1,2,5]
输出: True
限制:
数组长度为 5
数组的数取值为 [0, 13] .
class Solution {
public boolean isStraight(int[] nums) {
Set<Integer> hashSet=new HashSet<>();
int max=0;
int min=14;
for(int num:nums){
if(num==0)continue;
max=Math.max(max,num);
min=Math.min(min,num);
if(hashSet.contains(num)){
return false;
}
hashSet.add(num);
}
if(max-min<5){
return true;
}else{
return false;
}
}
}
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制:
1 <= target <= 10^5
脑子里都是暴力解法 ,
1.滑动窗口法
class Solution {
public int[][] findContinuousSequence(int target) {
//双指针
int left=1;
int right=1;
List<int []> list=new ArrayList<>();
int res=0;
while(left<=target/2){
if(res>target){
res-=left;
left++;
}else{
if(res==target){
//把左到右的数据放到数组中
int[] temp=new int[right-left];
for(int k=left;k<right;k++){
temp[k-left]=k;
}
list.add(temp);
res-=left;
left++;
}else{
//不够的话
res+=right;
right++;
}
}
}
return list.toArray(new int[list.size()][]);
}
}
2.永远令人沉默的数学法
class Solution {
public int[][] findContinuousSequence(int target) {
List<int[]> list=new ArrayList<>();
for(int i=1;i<=target/2;i++){
double j=(Math.sqrt(1+4*(2*target+Math.pow(i,2)-i))-1)/2;
if(j>i&&j==(int)j){
int[] temp=new int[(int)j-i+1];
for(int k=i;k<=j;k++){
temp[k-i]=k;
}
list.add(temp);
}
}
return list.toArray(new int[list.size()][]);
}
}
138.请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
提示:
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。
注意:本题与主站 138 题相同:https://leetcode-cn.com/problems/copy-list-with-random-pointer/
class Solution {
public Node copyRandomList(Node head) {
if(head==null){
return null;
}
Map<Node,Node> hashMap=new HashMap<>();
Node temp=head;
while(temp!=null){
hashMap.put(temp,new Node(temp.val));
temp=temp.next;
}
Node curr=head;
while(curr!=null){
hashMap.get(curr).next=hashMap.get(curr.next);//不能直接用curr.next,不然新建node没有意义
hashMap.get(curr).random=hashMap.get(curr.random);
curr=curr.next;
}
return hashMap.get(head);
}
}
必须node都是新建的,地址和原来不一样,不然就不是拷贝。
另一种方法是把节点一个一个插入原节点后面,然后把新链表拆出来。
class Solution {
public Node copyRandomList(Node head) {
//1.先插入节点
Node temp=head;
if(head==null){
return null;
}
while(temp!=null){
Node curr=new Node(temp.val);
curr.next=temp.next;
temp.next=curr;
temp=curr.next;
}
temp=head;
//2.加入random
while(temp!=null){
if(temp.random!=null){
temp.next.random=temp.random.next;
}
temp=temp.next.next;
}
//3.拆分出结果链表
Node res=head.next;
Node curr=head;
temp=head.next;
while(temp.next!=null){
curr.next=curr.next.next;
temp.next=temp.next.next;
curr=curr.next;
temp=temp.next;
}
curr.next=null;//注意最后一个节点要单独处理
return res;
}
}
56.在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
示例 2:输入:nums = [9,1,7,9,7,9,7]
输出:1
限制:
1 <= nums.length <= 10000
1 <= nums[i] < 2^31
统计每个比特位之和,找不能被3整除 的位,就是只出现了一次的数。
public int singleNumber(int[] nums) {
int[] count=new int[32];
for(int num:nums){
for(int i=0;i<32;i++){
count[i]+=(num&1);
num>>=1;
}
}
int res=0;
for(int i=0;i<32;i++){
//注意应该是左移了!!!
res<<=1;
res|=count[31-i]%3;
}
return res;
}
}
没学会这个。。
class Solution {
public int singleNumber(int[] nums) {
//数电杀我
int ones = 0, twos = 0;
for(int num : nums){
ones = ones ^ num & ~twos;
twos = twos ^ num & ~ones;
}
return ones;
}
}
66、给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
示例:
输入: [1,2,3,4,5]
输出: [120,60,40,30,24]
提示:
所有元素乘积之和不会溢出 32 位整数
a.length <= 100000
class Solution {
public int[] constructArr(int[] a) {
//做一个左乘积数组和右乘积数组
int length=a.length;
if(length==0){
return new int[0];
}
int[] left=new int[length];
int[] right=new int[length];
left[0]=1;
right[length-1]=1;
for(int i=1;i<length;i++){
left[i]=a[i-1]*left[i-1];
}
for(int i=length-2;i>=0;i--){
right[i]=a[i+1]*right[i+1];
}
int[] res=new int[length];
for(int i=0;i<length;i++){
res[i]=left[i]*right[i];
}
return res;
}
}
怎么优化空间复杂度??
class Solution {
public int[] constructArr(int[] a) {
//利用右指针存储右边的乘积
int length=a.length;
if(length==0){
return new int[0];
}
int[] res=new int[length];
res[0]=1;
for(int i=1;i<length;i++){
res[i]=a[i-1]*res[i-1];
}
int right=a[length-1];
for(int i=length-2;i>=0;i--){
res[i]=res[i]*right;
right*=a[i];
}
return res;
}
}
60.把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
示例 1:
输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]
示例 2:输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
限制:
1 <= n <= 11
class Solution {
public double[] dicesProbability(int n) {
//一生二
double[] pre={1/6d,1/6d,1/6d,1/6d,1/6d,1/6d};
for(int i=2;i<=n;i++){
double[] temp=new double[i*5+1];
for(int j=0;j<pre.length;j++){
for(int k=0;k<6;k++){
temp[j+k]+=pre[j]/6;
}
}
pre=temp;
}
return pre;
}
}