概览剑指offer
1.61 翻转单词顺序1.62 左旋转字符串1.63 滑动窗口的最大值1.64 队列的最大值 Android进阶
Android布局优化Android权限处理 总结
概览剑指offer:翻转单词顺序、左旋转字符串、滑动窗口的最大值、队列的最大值
Android进阶:Android布局优化、Android权限处理
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
示例 1: 输入: "the sky is blue" 输出: "blue is sky the"
//双指针 class Solution { public String reverseWords(String s) { s = s.trim(); // 删除首尾空格 int j = s.length() - 1, i = j; StringBuilder res = new StringBuilder(); while(i >= 0) { while(i >= 0 && s.charAt(i) != ' ') i--; // 搜索首个空格 res.append(s.substring(i + 1, j + 1) + " "); // 添加单词 while(i >= 0 && s.charAt(i) == ' ') i--; // 跳过单词间空格 j = i; // j 指向下个单词的尾字符 } return res.toString().trim(); // 转化为字符串并返回 } }1.62 左旋转字符串
字符串的左旋转 *** 作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转 *** 作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1: 输入: s = "abcdefg", k = 2 输出: "cdefgab"
//遍历字符加入尾部 class Solution { public String reverseLeftWords(String s, int n) { StringBuilder res = new StringBuilder(); for(int i = n; i < n + s.length(); i++) res.append(s.charAt(i % s.length())); //利用取模运算简化 return res.toString(); } }1.63 滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
//单调队列 //本题难点在于如何在每次窗口滑动后,将 “获取窗口内最大值” 的时间复杂度从 O(k) 降低至 O(1)。 //使用单调队列。遍历数组时,每轮保证单调队列 deque : //deque内仅包含窗口内的元素 ⇒ 每轮窗口滑动移除了元素 nums[i−1] ,需将 deque 内的对应元素一起删除。 //deque内的元素 非严格递减 ⇒ 每轮窗口滑动添加了元素 nums[j+1] ,需将 deque 内所有1.64 队列的最大值deque = new linkedList<>(); int[] res = new int[nums.length - k + 1]; // 未形成窗口 for(int i = 0; i < k; i++) { while(!deque.isEmpty() && deque.peekLast() < nums[i]) deque.removeLast(); deque.addLast(nums[i]); } res[0] = deque.peekFirst(); // 形成窗口后 for(int i = k; i < nums.length; i++) { if(deque.peekFirst() == nums[i - k]) deque.removeFirst(); while(!deque.isEmpty() && deque.peekLast() < nums[i]) deque.removeLast(); deque.addLast(nums[i]); res[i - k + 1] = deque.peekFirst(); } return res; } }
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
示例 1: 输入: ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"] [[],[1],[2],[],[],[]] 输出: [null,null,null,2,1,2]
//双端队列 //使用一个双端队列 deque,在每次入队时,如果 deque 队尾元素小于即将入队的元素 value,则将小于 value 的元素全部出队后,再将 value 入队;否则直接入队。 class MaxQueue { QueueAndroid进阶 Android布局优化q; Deque d; public MaxQueue() { q = new linkedList (); d = new linkedList (); } public int max_value() { if (d.isEmpty()) { return -1; } return d.peekFirst(); } public void push_back(int value) { while (!d.isEmpty() && d.peekLast() < value) { d.pollLast(); } d.offerLast(value); q.offer(value); } public int pop_front() { if (q.isEmpty()) { return -1; } int ans = q.poll(); if (ans == d.peekFirst()) { d.pollFirst(); } return ans; } }
标签在布局优化中是使用最多的一个标签了,它就是为了解决重复定义布局的问题。标签就相当于C、C++中的include头文件一样,把一些常用的底层的API封装起来,需要的时候引入即可。
标签都是与****标签组合使用的,它的作用就是可以有效减少View树的层次来优化布局。
另外有两点需要特别注意:
1.只可以作为xml layout的根节点。
2.当需要扩充的xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于 viewGroup中,同时需要设置attachToRoot为True。
ViewStub
在开发过程中,经常会遇到这样一种情况,有些布局很复杂但是却很少使用。例如条目详情、进度条标识或者未读消息等,这些情况如果在一开始初始化,虽然设置可见性 View.GONE ,但是在Inflate的时候View仍然会被Inflate,仍然会创建对象,由于这些布局又想到复杂,所以会很消耗系统资源。ViewStub就是为了解决上面问题的,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。
Android权限处理Android6.0以上把权限分为普通权限和危险权限,所以危险权限是需要动态申请,给予用户提示的。
危险权限都是一组一组的。 分组对权限机制的申请是有一定影响的。例如app运行在android 6.x的机器上,对于授权机制是这样的。如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS已经授权了,当你的app申请WRITE_CONTACTS时,系统会直接授权通过。
动态申请权限的逻辑:
开源项目
PermissionsDispatcher 使用注解的方式,动态生成类处理运行时权限.
Grant 简化运行时权限的处理,比较灵活
android-RuntimePermissions Google官方的例子
总结1.剑指算法将在明后两天结束,最近接近过年比较忙;
2.Android知识也基本快要结束了,争取年前结束,年后会查漏补缺;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)