937. 重新排列日志文件【简单题】【每日一题】
思路:
代码:
class Solution {
public String[] reorderLogFiles(String[] logs) {
//定义nums存放数字日志
List<String> nums = new ArrayList<>();
//定义strs存放字母日志
List<String> strs = new ArrayList<>();
//遍历日志数组,将数字日志和数字日志分离
for (String log : logs) {
char flag = log.split(" ")[1].charAt(0);
if (Character.isDigit(flag)){
nums.add(log);
}else {
strs.add(log);
}
}
//对字母日志使用lambda进行排序,根据题目要求
//1、字母日志在内容不同时,忽略标识符后按内容字母顺序排序 --> 字母日志以第一个空格为分界点,左侧为标识符,右侧为内容,因此可将日志的内容提取出来,为 log.substring(log.indexof(' '+1))
//2、字母日志在内容相同时,按标识符进行排序 -->因此还需要将标识符提取出来,为 log.substring(0,log.indexof(' '))
//3、标识符和内容均提取出来之后,即可使用lambda对strs进行排序
strs.sort((String a,String b) ->
a.substring(a.indexOf(' ')+1).compareTo(b.substring(b.indexOf(' ')+1)) == 0
?
a.substring(0,a.indexOf(' ')).compareTo(b.substring(0,b.indexOf(' ')))
:
a.substring(a.indexOf(' ')+1).compareTo(b.substring(b.indexOf(' ')+1)));
int i = 0,j = 0;
//根据题目要求,将字母日志排序之后优先输出,数字日志保持原来的顺序输出
for (int k = 0; k < logs.length; k++) {
if (i < strs.size()){//优先将排序后的strs输出
logs[k] = strs.get(i++);
}else {//当strs输出完毕之后,再输出nums
if (j < nums.size()){
logs[k] = nums.get(j++);
}
}
}
return logs;
}
}
剑指 Offer II 026. 重排链表【中等题】
思路:【寻找链表中点+翻转链表+合并链表】
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
/**
* 1.找出链表的中间节点
* 2.根据中间节点将链表分为左半部分和右半部分
* 3.将右半部分翻转
* 4.将左半部分和右半部分交叉合并
*/
//1.找出中间节点
ListNode cnt = head;
int count = 0;
while(cnt != null){
cnt = cnt.next;
count++;
}
ListNode left = head,right = null;
int index = 0,half = (count-1)/2;
while(index < half){
head = head.next;
index++;
}
//2.将原链表分为左链表和右链表
right = head.next;
head.next = null;
//3.将右链表翻转
ListNode cur = right,reverse = null;
while(cur != null){
ListNode next = cur.next;
cur.next = reverse;
reverse = cur;
cur = next;
}
right = reverse;
//4.将左半部分与右半部分交叉合并
ListNode nextLeft = null,nextRight = null;
while(left != null && right != null){
//求出left和right当前节点指针的下一个节点
nextLeft = left.next;
nextRight = right.next;
//将left指针下一个指向改为right,将right下一个指向改为原本left的下一个指向
left.next = right;
right.next = nextLeft;
//将left和right指针按原来顺序右移
left = nextLeft;
right = nextRight;
}
}
}
剑指 Offer II 027. 回文链表【简单题】
思路:
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
/**
* 1.找出链表最中间的节点
* 2.以中间节点为界将给定链表分为左链表和右链表
* 3.将右链表翻转
* 4.同时从左链表和右链表的头节点开始遍历整个链表,如果是回文链表,那么每一个遍历到的链表都应该相等
*/
// 1.找出中间节点
int cnt = 0;
ListNode rightNode = head;
while(rightNode != null){
cnt++;
rightNode = rightNode.next;
}
// System.out.println(cnt);
ListNode left = head,right = null;
int index = 0,half = (cnt-1)/2;
while(index < half){
head = head.next;
index++;
}
// 2.将原链表分为左链表和右链表,考虑到原链表为奇数时左右链表长度不等,于是当为奇数时,截掉最中间那个节点
right = head.next;
if(cnt % 2 == 1){
head = null;
}else{
head.next = null;
}
// 3.将右链表翻转
ListNode cur = right,reverse = null;
while(cur != null){
ListNode next = cur.next;
cur.next = reverse;
reverse = cur;
cur = next;
}
right = reverse;
// 4.同时从头节点遍历左右两个链表,如果对应节点的值相同,则继续遍历,如果不相同则返回false,最后全部遍历结束则返回true
while(left != null && right != null){
if(left.val != right.val){
return false;
}
left = left.next;
right = right.next;
}
return true;
}
}