**15、二进制中1的个数 **
题目描述: 请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如,把9表示成二进制是1001,有2位是1。因此,如果输入9,则该函数输出2。
:
把一个整数减去1,再和原整数做‘与’运算,会把该整数最右边一个1变成0,其它位不变。那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
public class Solution {
public int hammingWeight(int n) {
int sum=0; //计数器sum
while(n!=0){
n = n&(n-1); //每次把n的二进制最后一个1变为0
//n &= (n-1);
sum++;
}return sum;
}
}
17、打印从1到最大的n位数
题目描述: 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
: 暂不考虑大数问题
class Solution {
public int[] printNumbers(int n) {
int size=(int)Math.pow(10,n)-1;
int[] array=new int[size];
for(int i=0;i<size;i++){
array[i]=i+1;
}return array;
}
}
**29、顺时针打印矩阵 **
**题目描述:**输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
:
通过一个flag变量去不断的去更新遍历矩阵下标x,y的值(通过越界和flag当前的值)
class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> ans = new ArrayList<>();
int flag = 1;// 1->right, 2->down, 3->left, 4->up
int x = 0;
int y = 0;
boolean[][] vis = new boolean[matrix.length][matrix[0].length]; // 这个就是用来标记已经走过的点
while (ans.size() < matrix.length * matrix[0].length) {
if(x < 0 || x >= matrix.length || y < 0 || y >= matrix[0].length || vis[x][y]) {
// vis[x][y] -> 已经遍历过的位置也当作越界处理
if(flag == 1) {
flag = 2; // 往下走
y--; // 消除越界的影响
x++; // 本质上就是到达下一个位置的横坐标
} else if(flag == 2) {
flag = 3; // 往左走
x--; // 消除越界的影响
y--; // 本质上就是到达下一个位置的纵坐标
} else if (flag == 3) {
flag = 4; // 往上走
y++; // 消除越界的影响
x--; // 本质上就是到达下一个位置的横坐标
} else {
flag = 1;//往右走
x++; // 消除越界的影响
y++; // 本质上就是到达下一个位置的纵坐标
}
} else {
ans.add(matrix[x][y]);
vis[x][y] = true; // 去标记已经遍历过的位置
// 根据flag的值更新遍历矩阵的下标x,y的值
if(flag == 1) {
y++;
} else if (flag == 2) {
x++;
} else if (flag == 3) {
y--;
} else {
x--;
}
}
}
return ans;
}
}
30、包含min函数的栈
**题目描述:**定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数,在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)
:
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.min();
*/
class MinStack {
Stack<Integer> s1;
Stack<Integer> s2;
/** initialize your data structure here. */
public MinStack() {
s1=new Stack();
s2=new Stack(); //s2是辅助栈
}
public void push(int x) {
s1.push(x);
//加等号的边界条件
if(s2.isEmpty() || x<=s2.peek() ){ //注意if( )顺序,s2不空是s2.peek()的前提
s2.push(x);
}
}
public void pop() {
if(s1.pop().equals(s2.peek())){ //无论是否,都会执行s1.pop()
s2.pop();
}
}
public int top() {
return s1.peek();
}
public int min() {
return s2.peek();
}
}
31、栈的压入,弹出序列
**题目描述:**输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
:
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack=new Stack();
int i=0; //poped的指针
for(int j=0; j<pushed.length; j++){
stack.push(pushed[j]); //将pushed元素逐个放入栈中
//for(int num : pushed){
//stack.push(num);
while(!stack.isEmpty() && stack.peek()== popped[i]){ //如果栈顶元素和poped元素相等,则将栈顶元素弹出
stack.pop();
i++;
}
}return stack.isEmpty();
}
}
:
for(数据类型 变量名:对象) //for(int num : pushed)
{
//循环体为引用了变量的Java语句 //stack.push(num);
}
33、二叉搜索树的后序遍历序列
题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同
:
public class Solution{
public boolean verifyPostorder(int[] postorder) {
return helper(postorder, 0, postorder.length - 1);
}
boolean helper(int[] postorder, int left, int right) {
//如果left==right,就一个节点不需要判断了,如果left>right说明没有节点,
//也不用再看了,否则就要继续往下判断
if (left >= right){
return true;
}
//因为数组中最后一个值postorder[right]是根节点,这里从左往右找出第一个比
//根节点大的值,他后面的都是根节点的右子节点(包含当前值,不包含最后一个值,
//因为最后一个是根节点),他前面的都是根节点的左子节点
int mid = left;
int root = postorder[right];
while (postorder[mid] < root){
mid++;
}
int temp = mid;
//因为postorder[mid]前面的值都是比根节点root小的,
//我们还需要确定postorder[mid]后面的值都要比根节点root大,
//如果后面有比根节点小的直接返回false
while (temp < right) {
if (postorder[temp++] < root)
return false;
}
//然后对左右子节点进行递归调用
return helper(postorder, left, mid - 1) && helper(postorder, mid, right - 1);
}
}
34、二叉树中和为某一值的路径
**题目描述:**输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
:
class Solution {
LinkedList<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> path = new LinkedList<>(); //初始化路径列表path
public List<List<Integer>> pathSum(TreeNode root, int sum) {
recur(root, sum);
return res;
}
void recur(TreeNode root, int tar) {
if(root == null) return;
path.add(root.val);
tar -= root.val; //更新目标值tar
if(tar == 0 && root.left == null && root.right == null)
res.add(new LinkedList(path));
recur(root.left, tar);
recur(root.right, tar);
path.removeLast();
}
}
36、 二叉搜索树与双向链表
**题目描述:**输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
:
40、 最小的k个数
**题目描述:**输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
:
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
//最小堆
Queue<Integer> queue=new PriorityQueue<>( (o1,o2)->o2.compareTo(o1) );
for(int i:arr){
queue.add(i);
//维护堆的最大个数为k
while(!queue.isEmpty()&&queue.size()>k){
queue.poll();
}
}
int[] res=new int[k];
for(int i=0;i<k;i++){
res[i]=queue.poll();
}
return res;
}
}
:
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(arr==null||arr.length==0){
return new int[0];
}
int low=0; int high=arr.length-1;
while(low<high){
int index=partition(arr,low,high);
if(index==k-1){break;}
//index<k-1相当于想要获得80分,结果获得60分,只需要在61分以上寻找
else if(index<k-1){low=index+1;}
else{high=index-1;}
}
//返回arr数组中,第0到第k-1一共k个数
return Arrays.copyOfRange(arr,0,k);
}
//partition函数
public int partition(int[] arr,int low,int high){
int piovt=arr[low];
int index=low;
for(int i=low;i<arr.length;i++){
if(arr[i]<piovt){
swap(arr,i,++index);
}
}
swap(arr,low,index);
return index;
}
public void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
43、1~n整数中1出现的次数
:暴力法,时间复杂度O(n*log(n))
class Solution {
public int countDigitOne(int n) {
int sum=0; //统计出现1的个数
for(int i=1;i<=n;i++){
int x=i;
while(x!=0){
if(x%10==1){ //%是取余
sum++;
}
x=x/10; //除号是取整
}
}
return sum;
}
}
49、丑数
题目描述:
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数
:
就是说通过去根据2* 丑数,3* 丑数,5* 丑数 这三个队列去判断出当前位置的值,然后去更新遍历这三个队列下标的值即可
public class solution{
public int GetUglyNumber_Solution(int index) {
int[] a = new int[index];
a[0] = 1;
int index1 = 0; // 遍历丑数*2的队列
int index2 = 0; // 遍历丑数*3的队列
int index3 = 0; // 遍历丑数*5的队列
for (int i = 1; i < index; i++) {
a[i] = Math.min(Math.min(a[index1] * 2, a[index2] * 3) , a[index3] * 5);
// 根据放在第i个位置上的数字更新遍历三个队列的下标
if (a[i] == a[index1] * 2) {
index1++;
}
if (a[i] == a[index2] * 3) {
index2++;
}
if (a[i] == a[index3] * 5) {
index3++;
}
}
return a[index - 1];
}
}